Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers crl.c Source File

crl.c

00001 /* crl.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   /* Name change compatibility layer no longer needs included here */
00024 
00025 #ifdef HAVE_CONFIG_H
00026     #include <config.h>
00027 #endif
00028 
00029 #include <wolfssl/wolfcrypt/settings.h>
00030 
00031 #ifndef WOLFCRYPT_ONLY
00032 #ifdef HAVE_CRL
00033 
00034 #include <wolfssl/internal.h>
00035 #include <wolfssl/error-ssl.h>
00036 
00037 #ifndef NO_FILESYSTEM
00038     #include <dirent.h>
00039     #include <sys/stat.h>
00040 #endif
00041 
00042 #include <string.h>
00043 
00044 #ifdef HAVE_CRL_MONITOR
00045     static int StopMonitor(int mfd);
00046 #endif
00047 
00048 
00049 /* Initialize CRL members */
00050 int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
00051 {
00052     WOLFSSL_ENTER("InitCRL");
00053 
00054     crl->cm = cm;
00055     crl->crlList = NULL;
00056     crl->monitors[0].path = NULL;
00057     crl->monitors[1].path = NULL;
00058 #ifdef HAVE_CRL_MONITOR
00059     crl->tid   =  0;
00060     crl->mfd   = -1;    /* mfd for bsd is kqueue fd, eventfd for linux */
00061     crl->setup = 0;     /* thread setup done predicate */
00062     if (pthread_cond_init(&crl->cond, 0) != 0) {
00063         WOLFSSL_MSG("Pthread condition init failed");
00064         return BAD_COND_E;
00065     }
00066 #endif
00067     if (InitMutex(&crl->crlLock) != 0) {
00068         WOLFSSL_MSG("Init Mutex failed");
00069         return BAD_MUTEX_E;
00070     }
00071 
00072     return 0;
00073 }
00074 
00075 
00076 /* Initialize CRL Entry */
00077 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl)
00078 {
00079     WOLFSSL_ENTER("InitCRL_Entry");
00080 
00081     XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
00082     /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
00083      *   copy the hash here if needed for optimized comparisons */
00084     XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
00085     XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
00086     crle->lastDateFormat = dcrl->lastDateFormat;
00087     crle->nextDateFormat = dcrl->nextDateFormat;
00088 
00089     crle->certs = dcrl->certs;   /* take ownsership */
00090     dcrl->certs = NULL;
00091     crle->totalCerts = dcrl->totalCerts;
00092 
00093     return 0;
00094 }
00095 
00096 
00097 /* Free all CRL Entry resources */
00098 static void FreeCRL_Entry(CRL_Entry* crle)
00099 {
00100     RevokedCert* tmp = crle->certs;
00101 
00102     WOLFSSL_ENTER("FreeCRL_Entry");
00103 
00104     while(tmp) {
00105         RevokedCert* next = tmp->next;
00106         XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
00107         tmp = next;
00108     }
00109 }
00110 
00111 
00112 
00113 /* Free all CRL resources */
00114 void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
00115 {
00116     CRL_Entry* tmp = crl->crlList;
00117 
00118     WOLFSSL_ENTER("FreeCRL");
00119 
00120     if (crl->monitors[0].path)
00121         XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
00122 
00123     if (crl->monitors[1].path)
00124         XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
00125 
00126     while(tmp) {
00127         CRL_Entry* next = tmp->next;
00128         FreeCRL_Entry(tmp);
00129         XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY);
00130         tmp = next;
00131     }
00132 
00133 #ifdef HAVE_CRL_MONITOR
00134     if (crl->tid != 0) {
00135         WOLFSSL_MSG("stopping monitor thread");
00136         if (StopMonitor(crl->mfd) == 0)
00137             pthread_join(crl->tid, NULL);
00138         else {
00139             WOLFSSL_MSG("stop monitor failed");
00140         }
00141     }
00142     pthread_cond_destroy(&crl->cond);
00143 #endif
00144     FreeMutex(&crl->crlLock);
00145     if (dynamic)   /* free self */
00146         XFREE(crl, NULL, DYNAMIC_TYPE_CRL);
00147 }
00148 
00149 
00150 /* Is the cert ok with CRL, return 0 on success */
00151 int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
00152 {
00153     CRL_Entry* crle;
00154     int        foundEntry = 0;
00155     int        ret = 0;
00156 
00157     WOLFSSL_ENTER("CheckCertCRL");
00158 
00159     if (LockMutex(&crl->crlLock) != 0) {
00160         WOLFSSL_MSG("LockMutex failed");
00161         return BAD_MUTEX_E;
00162     }
00163 
00164     crle = crl->crlList;
00165 
00166     while (crle) {
00167         if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
00168             int doNextDate = 1;
00169 
00170             WOLFSSL_MSG("Found CRL Entry on list");
00171             WOLFSSL_MSG("Checking next date validity");
00172 
00173             #ifdef WOLFSSL_NO_CRL_NEXT_DATE
00174                 if (crle->nextDateFormat == ASN_OTHER_TYPE)
00175                     doNextDate = 0;  /* skip */
00176             #endif
00177 
00178             if (doNextDate && !ValidateDate(crle->nextDate,
00179                                             crle->nextDateFormat, AFTER)) {
00180                 WOLFSSL_MSG("CRL next date is no longer valid");
00181                 ret = ASN_AFTER_DATE_E;
00182             }
00183             else
00184                 foundEntry = 1;
00185             break;
00186         }
00187         crle = crle->next;
00188     }
00189 
00190     if (foundEntry) {
00191         RevokedCert* rc = crle->certs;
00192 
00193         while (rc) {
00194             if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
00195                 WOLFSSL_MSG("Cert revoked");
00196                 ret = CRL_CERT_REVOKED;
00197                 break;
00198             }
00199             rc = rc->next;
00200         }
00201     }
00202 
00203     UnLockMutex(&crl->crlLock);
00204 
00205     if (foundEntry == 0) {
00206         WOLFSSL_MSG("Couldn't find CRL for status check");
00207         ret = CRL_MISSING;
00208         if (crl->cm->cbMissingCRL) {
00209             char url[256];
00210 
00211             WOLFSSL_MSG("Issuing missing CRL callback");
00212             url[0] = '\0';
00213             if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
00214                 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
00215                 url[cert->extCrlInfoSz] = '\0';
00216             }
00217             else  {
00218                 WOLFSSL_MSG("CRL url too long");
00219             }
00220             crl->cm->cbMissingCRL(url);
00221         }
00222     }
00223 
00224 
00225     return ret;
00226 }
00227 
00228 
00229 /* Add Decoded CRL, 0 on success */
00230 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl)
00231 {
00232     CRL_Entry* crle;
00233 
00234     WOLFSSL_ENTER("AddCRL");
00235 
00236     crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
00237     if (crle == NULL) {
00238         WOLFSSL_MSG("alloc CRL Entry failed");
00239         return -1;
00240     }
00241 
00242     if (InitCRL_Entry(crle, dcrl) < 0) {
00243         WOLFSSL_MSG("Init CRL Entry failed");
00244         XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
00245         return -1;
00246     }
00247 
00248     if (LockMutex(&crl->crlLock) != 0) {
00249         WOLFSSL_MSG("LockMutex failed");
00250         FreeCRL_Entry(crle);
00251         XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
00252         return BAD_MUTEX_E;
00253     }
00254     crle->next = crl->crlList;
00255     crl->crlList = crle;
00256     UnLockMutex(&crl->crlLock);
00257 
00258     return 0;
00259 }
00260 
00261 
00262 /* Load CRL File of type, SSL_SUCCESS on ok */
00263 int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type)
00264 {
00265     int          ret = SSL_SUCCESS;
00266     const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
00267     DerBuffer*   der = NULL;
00268 #ifdef WOLFSSL_SMALL_STACK
00269     DecodedCRL*  dcrl;
00270 #else
00271     DecodedCRL   dcrl[1];
00272 #endif
00273 
00274     WOLFSSL_ENTER("BufferLoadCRL");
00275 
00276     if (crl == NULL || buff == NULL || sz == 0)
00277         return BAD_FUNC_ARG;
00278 
00279     if (type == SSL_FILETYPE_PEM) {
00280         int eccKey = 0;   /* not used */
00281         EncryptedInfo info;
00282         info.ctx = NULL;
00283 
00284         ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
00285         if (ret == 0) {
00286             myBuffer = der->buffer;
00287             sz = der->length;
00288         }
00289         else {
00290             WOLFSSL_MSG("Pem to Der failed");
00291             FreeDer(&der);
00292             return -1;
00293         }
00294     }
00295 
00296 #ifdef WOLFSSL_SMALL_STACK
00297     dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
00298     if (dcrl == NULL) {
00299         FreeDer(&der);
00300         return MEMORY_E;
00301     }
00302 #endif
00303 
00304     InitDecodedCRL(dcrl);
00305     ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
00306     if (ret != 0) {
00307         WOLFSSL_MSG("ParseCRL error");
00308     }
00309     else {
00310         ret = AddCRL(crl, dcrl);
00311         if (ret != 0) {
00312             WOLFSSL_MSG("AddCRL error");
00313         }
00314     }
00315 
00316     FreeDecodedCRL(dcrl);
00317 
00318 #ifdef WOLFSSL_SMALL_STACK
00319     XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00320 #endif
00321 
00322     FreeDer(&der);
00323 
00324     return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */
00325 }
00326 
00327 
00328 #ifdef HAVE_CRL_MONITOR
00329 
00330 
00331 /* Signal Monitor thread is setup, save status to setup flag, 0 on success */
00332 static int SignalSetup(WOLFSSL_CRL* crl, int status)
00333 {
00334     int ret;
00335 
00336     /* signal to calling thread we're setup */
00337     if (LockMutex(&crl->crlLock) != 0) {
00338         WOLFSSL_MSG("LockMutex crlLock failed");
00339         return BAD_MUTEX_E;
00340     }
00341 
00342         crl->setup = status;
00343         ret = pthread_cond_signal(&crl->cond);
00344 
00345     UnLockMutex(&crl->crlLock);
00346 
00347     if (ret != 0)
00348         return BAD_COND_E;
00349 
00350     return 0;
00351 }
00352 
00353 
00354 /* read in new CRL entries and save new list */
00355 static int SwapLists(WOLFSSL_CRL* crl)
00356 {
00357     int        ret;
00358     CRL_Entry* newList;
00359 #ifdef WOLFSSL_SMALL_STACK
00360     WOLFSSL_CRL* tmp;
00361 #else
00362     WOLFSSL_CRL tmp[1];
00363 #endif
00364 
00365 #ifdef WOLFSSL_SMALL_STACK
00366     tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
00367     if (tmp == NULL)
00368         return MEMORY_E;
00369 #endif
00370 
00371     if (InitCRL(tmp, crl->cm) < 0) {
00372         WOLFSSL_MSG("Init tmp CRL failed");
00373 #ifdef WOLFSSL_SMALL_STACK
00374         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00375 #endif
00376         return -1;
00377     }
00378 
00379     if (crl->monitors[0].path) {
00380         ret = LoadCRL(tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0);
00381         if (ret != SSL_SUCCESS) {
00382             WOLFSSL_MSG("PEM LoadCRL on dir change failed");
00383             FreeCRL(tmp, 0);
00384 #ifdef WOLFSSL_SMALL_STACK
00385             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00386 #endif
00387             return -1;
00388         }
00389     }
00390 
00391     if (crl->monitors[1].path) {
00392         ret = LoadCRL(tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0);
00393         if (ret != SSL_SUCCESS) {
00394             WOLFSSL_MSG("DER LoadCRL on dir change failed");
00395             FreeCRL(tmp, 0);
00396 #ifdef WOLFSSL_SMALL_STACK
00397             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00398 #endif
00399             return -1;
00400         }
00401     }
00402 
00403     if (LockMutex(&crl->crlLock) != 0) {
00404         WOLFSSL_MSG("LockMutex failed");
00405         FreeCRL(tmp, 0);
00406 #ifdef WOLFSSL_SMALL_STACK
00407         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00408 #endif
00409         return -1;
00410     }
00411 
00412     newList = tmp->crlList;
00413 
00414     /* swap lists */
00415     tmp->crlList  = crl->crlList;
00416     crl->crlList = newList;
00417 
00418     UnLockMutex(&crl->crlLock);
00419 
00420     FreeCRL(tmp, 0);
00421 
00422 #ifdef WOLFSSL_SMALL_STACK
00423     XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00424 #endif
00425 
00426     return 0;
00427 }
00428 
00429 
00430 #if (defined(__MACH__) || defined(__FreeBSD__))
00431 
00432 #include <sys/types.h>
00433 #include <sys/event.h>
00434 #include <sys/time.h>
00435 #include <fcntl.h>
00436 #include <unistd.h>
00437 
00438 #ifdef __MACH__
00439     #define XEVENT_MODE O_EVTONLY
00440 #elif defined(__FreeBSD__)
00441     #define XEVENT_MODE EVFILT_VNODE
00442 #endif
00443 
00444 
00445 /* we need a unique kqueue user filter fd for crl in case user is doing custom
00446  * events too */
00447 #ifndef CRL_CUSTOM_FD
00448     #define CRL_CUSTOM_FD 123456
00449 #endif
00450 
00451 
00452 /* shutdown monitor thread, 0 on success */
00453 static int StopMonitor(int mfd)
00454 {
00455     struct kevent change;
00456 
00457     /* trigger custom shutdown */
00458     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
00459     if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
00460         WOLFSSL_MSG("kevent trigger customer event failed");
00461         return -1;
00462     }
00463 
00464     return 0;
00465 }
00466 
00467 
00468 /* OS X  monitoring */
00469 static void* DoMonitor(void* arg)
00470 {
00471     int fPEM, fDER;
00472     struct kevent change;
00473 
00474     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
00475 
00476     WOLFSSL_ENTER("DoMonitor");
00477 
00478     crl->mfd = kqueue();
00479     if (crl->mfd == -1) {
00480         WOLFSSL_MSG("kqueue failed");
00481         SignalSetup(crl, MONITOR_SETUP_E);
00482         return NULL;
00483     }
00484 
00485     /* listen for custom shutdown event */
00486     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
00487     if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
00488         WOLFSSL_MSG("kevent monitor customer event failed");
00489         SignalSetup(crl, MONITOR_SETUP_E);
00490         close(crl->mfd);
00491         return NULL;
00492     }
00493 
00494     fPEM = -1;
00495     fDER = -1;
00496 
00497     if (crl->monitors[0].path) {
00498         fPEM = open(crl->monitors[0].path, XEVENT_MODE);
00499         if (fPEM == -1) {
00500             WOLFSSL_MSG("PEM event dir open failed");
00501             SignalSetup(crl, MONITOR_SETUP_E);
00502             close(crl->mfd);
00503             return NULL;
00504         }
00505     }
00506 
00507     if (crl->monitors[1].path) {
00508         fDER = open(crl->monitors[1].path, XEVENT_MODE);
00509         if (fDER == -1) {
00510             WOLFSSL_MSG("DER event dir open failed");
00511             if (fPEM != -1)
00512                 close(fPEM);
00513             close(crl->mfd);
00514             SignalSetup(crl, MONITOR_SETUP_E);
00515             return NULL;
00516         }
00517     }
00518 
00519     if (fPEM != -1)
00520         EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
00521                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
00522 
00523     if (fDER != -1)
00524         EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
00525                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
00526 
00527     /* signal to calling thread we're setup */
00528     if (SignalSetup(crl, 1) != 0) {
00529         if (fPEM != -1)
00530             close(fPEM);
00531         if (fDER != -1)
00532             close(fDER);
00533         close(crl->mfd);
00534         return NULL;
00535     }
00536 
00537     for (;;) {
00538         struct kevent event;
00539         int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
00540 
00541         WOLFSSL_MSG("Got kevent");
00542 
00543         if (numEvents == -1) {
00544             WOLFSSL_MSG("kevent problem, continue");
00545             continue;
00546         }
00547 
00548         if (event.filter == EVFILT_USER) {
00549             WOLFSSL_MSG("Got user shutdown event, breaking out");
00550             break;
00551         }
00552 
00553         if (SwapLists(crl) < 0) {
00554             WOLFSSL_MSG("SwapLists problem, continue");
00555         }
00556     }
00557 
00558     if (fPEM != -1)
00559         close(fPEM);
00560     if (fDER != -1)
00561         close(fDER);
00562 
00563     close(crl->mfd);
00564 
00565     return NULL;
00566 }
00567 
00568 
00569 #elif defined(__linux__)
00570 
00571 #include <sys/types.h>
00572 #include <sys/inotify.h>
00573 #include <sys/eventfd.h>
00574 #include <unistd.h>
00575 
00576 
00577 #ifndef max
00578     static INLINE int max(int a, int b)
00579     {
00580         return a > b ? a : b;
00581     }
00582 #endif /* max */
00583 
00584 
00585 /* shutdown monitor thread, 0 on success */
00586 static int StopMonitor(int mfd)
00587 {
00588     word64 w64 = 1;
00589 
00590     /* write to our custom event */
00591     if (write(mfd, &w64, sizeof(w64)) < 0) {
00592         WOLFSSL_MSG("StopMonitor write failed");
00593         return -1;
00594     }
00595 
00596     return 0;
00597 }
00598 
00599 
00600 /* linux monitoring */
00601 static void* DoMonitor(void* arg)
00602 {
00603     int         notifyFd;
00604     int         wd  = -1;
00605     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
00606 #ifdef WOLFSSL_SMALL_STACK
00607     char*       buff;
00608 #else
00609     char        buff[8192];
00610 #endif
00611 
00612     WOLFSSL_ENTER("DoMonitor");
00613 
00614     crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
00615     if (crl->mfd < 0) {
00616         WOLFSSL_MSG("eventfd failed");
00617         SignalSetup(crl, MONITOR_SETUP_E);
00618         return NULL;
00619     }
00620 
00621     notifyFd = inotify_init();
00622     if (notifyFd < 0) {
00623         WOLFSSL_MSG("inotify failed");
00624         close(crl->mfd);
00625         SignalSetup(crl, MONITOR_SETUP_E);
00626         return NULL;
00627     }
00628 
00629     if (crl->monitors[0].path) {
00630         wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
00631                                                                 IN_DELETE);
00632         if (wd < 0) {
00633             WOLFSSL_MSG("PEM notify add watch failed");
00634             close(crl->mfd);
00635             close(notifyFd);
00636             SignalSetup(crl, MONITOR_SETUP_E);
00637             return NULL;
00638         }
00639     }
00640 
00641     if (crl->monitors[1].path) {
00642         wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
00643                                                                 IN_DELETE);
00644         if (wd < 0) {
00645             WOLFSSL_MSG("DER notify add watch failed");
00646             close(crl->mfd);
00647             close(notifyFd);
00648             SignalSetup(crl, MONITOR_SETUP_E);
00649             return NULL;
00650         }
00651     }
00652 
00653 #ifdef WOLFSSL_SMALL_STACK
00654     buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00655     if (buff == NULL)
00656         return NULL;
00657 #endif
00658 
00659     /* signal to calling thread we're setup */
00660     if (SignalSetup(crl, 1) != 0) {
00661         #ifdef WOLFSSL_SMALL_STACK
00662             XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00663         #endif
00664 
00665         if (wd > 0)
00666             inotify_rm_watch(notifyFd, wd);
00667         close(crl->mfd);
00668         close(notifyFd);
00669         return NULL;
00670     }
00671 
00672     for (;;) {
00673         fd_set readfds;
00674         int    result;
00675         int    length;
00676 
00677         FD_ZERO(&readfds);
00678         FD_SET(notifyFd, &readfds);
00679         FD_SET(crl->mfd, &readfds);
00680 
00681         result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
00682 
00683         WOLFSSL_MSG("Got notify event");
00684 
00685         if (result < 0) {
00686             WOLFSSL_MSG("select problem, continue");
00687             continue;
00688         }
00689 
00690         if (FD_ISSET(crl->mfd, &readfds)) {
00691             WOLFSSL_MSG("got custom shutdown event, breaking out");
00692             break;
00693         }
00694 
00695         length = (int) read(notifyFd, buff, 8192);
00696         if (length < 0) {
00697             WOLFSSL_MSG("notify read problem, continue");
00698             continue;
00699         }
00700 
00701         if (SwapLists(crl) < 0) {
00702             WOLFSSL_MSG("SwapLists problem, continue");
00703         }
00704     }
00705 
00706 #ifdef WOLFSSL_SMALL_STACK
00707     XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00708 #endif
00709 
00710     if (wd > 0)
00711         inotify_rm_watch(notifyFd, wd);
00712     close(crl->mfd);
00713     close(notifyFd);
00714 
00715     return NULL;
00716 }
00717 
00718 
00719 #else
00720 
00721 #error "CRL monitor only currently supported on linux or mach"
00722 
00723 #endif /* MACH or linux */
00724 
00725 
00726 /* Start Monitoring the CRL path(s) in a thread */
00727 static int StartMonitorCRL(WOLFSSL_CRL* crl)
00728 {
00729     int ret = SSL_SUCCESS;
00730 
00731     WOLFSSL_ENTER("StartMonitorCRL");
00732 
00733     if (crl == NULL)
00734         return BAD_FUNC_ARG;
00735 
00736     if (crl->tid != 0) {
00737         WOLFSSL_MSG("Monitor thread already running");
00738         return ret;  /* that's ok, someone already started */
00739     }
00740 
00741     if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) {
00742         WOLFSSL_MSG("Thread creation error");
00743         return THREAD_CREATE_E;
00744     }
00745 
00746     /* wait for setup to complete */
00747     if (LockMutex(&crl->crlLock) != 0) {
00748         WOLFSSL_MSG("LockMutex crlLock error");
00749         return BAD_MUTEX_E;
00750     }
00751 
00752         while (crl->setup == 0) {
00753             if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) {
00754                 ret = BAD_COND_E;
00755                 break;
00756             }
00757         }
00758 
00759         if (crl->setup < 0)
00760             ret = crl->setup;  /* store setup error */
00761 
00762     UnLockMutex(&crl->crlLock);
00763 
00764     if (ret < 0) {
00765         WOLFSSL_MSG("DoMonitor setup failure");
00766         crl->tid = 0;  /* thread already done */
00767     }
00768 
00769     return ret;
00770 }
00771 
00772 
00773 #else /* HAVE_CRL_MONITOR */
00774 
00775 #ifndef NO_FILESYSTEM
00776 
00777 static int StartMonitorCRL(WOLFSSL_CRL* crl)
00778 {
00779     (void)crl;
00780 
00781     WOLFSSL_ENTER("StartMonitorCRL");
00782     WOLFSSL_MSG("Not compiled in");
00783 
00784     return NOT_COMPILED_IN;
00785 }
00786 
00787 #endif /* NO_FILESYSTEM */
00788 
00789 #endif  /* HAVE_CRL_MONITOR */
00790 
00791 #ifndef NO_FILESYSTEM
00792 
00793 /* Load CRL path files of type, SSL_SUCCESS on ok */
00794 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
00795 {
00796     struct dirent* entry;
00797     DIR*           dir;
00798     int            ret = SSL_SUCCESS;
00799 #ifdef WOLFSSL_SMALL_STACK
00800     char*          name;
00801 #else
00802     char           name[MAX_FILENAME_SZ];
00803 #endif
00804 
00805     WOLFSSL_ENTER("LoadCRL");
00806     if (crl == NULL)
00807         return BAD_FUNC_ARG;
00808 
00809     dir = opendir(path);
00810     if (dir == NULL) {
00811         WOLFSSL_MSG("opendir path crl load failed");
00812         return BAD_PATH_ERROR;
00813     }
00814 
00815 #ifdef WOLFSSL_SMALL_STACK
00816     name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00817     if (name == NULL)
00818         return MEMORY_E;
00819 #endif
00820 
00821     while ( (entry = readdir(dir)) != NULL) {
00822         struct stat s;
00823 
00824         XMEMSET(name, 0, MAX_FILENAME_SZ);
00825         XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
00826         XSTRNCAT(name, "/", 1);
00827         XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
00828 
00829         if (stat(name, &s) != 0) {
00830             WOLFSSL_MSG("stat on name failed");
00831             continue;
00832         }
00833         if (s.st_mode & S_IFREG) {
00834 
00835             if (type == SSL_FILETYPE_PEM) {
00836                 if (XSTRSTR(entry->d_name, ".pem") == NULL) {
00837                     WOLFSSL_MSG("not .pem file, skipping");
00838                     continue;
00839                 }
00840             }
00841             else {
00842                 if (XSTRSTR(entry->d_name, ".der") == NULL &&
00843                     XSTRSTR(entry->d_name, ".crl") == NULL) {
00844 
00845                     WOLFSSL_MSG("not .der or .crl file, skipping");
00846                     continue;
00847                 }
00848             }
00849 
00850             if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
00851                                                                != SSL_SUCCESS) {
00852                 WOLFSSL_MSG("CRL file load failed, continuing");
00853             }
00854         }
00855     }
00856 
00857 #ifdef WOLFSSL_SMALL_STACK
00858     XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
00859 #endif
00860 
00861     if (monitor & WOLFSSL_CRL_MONITOR) {
00862         word32 pathLen;
00863         char* pathBuf;
00864 
00865         WOLFSSL_MSG("monitor path requested");
00866 
00867         pathLen = (word32)XSTRLEN(path);
00868         pathBuf = (char*)XMALLOC(pathLen+1, NULL, DYNAMIC_TYPE_CRL_MONITOR);
00869         if (pathBuf) {
00870             XSTRNCPY(pathBuf, path, pathLen);
00871             pathBuf[pathLen] = '\0'; /* Null Terminate */
00872 
00873             if (type == SSL_FILETYPE_PEM) {
00874                 crl->monitors[0].path = pathBuf;
00875                 crl->monitors[0].type = SSL_FILETYPE_PEM;
00876             } else {
00877                 crl->monitors[1].path = pathBuf;
00878                 crl->monitors[1].type = SSL_FILETYPE_ASN1;
00879             }
00880 
00881             if (monitor & WOLFSSL_CRL_START_MON) {
00882                 WOLFSSL_MSG("start monitoring requested");
00883 
00884                 ret = StartMonitorCRL(crl);
00885             }
00886         }
00887         else {
00888             ret = MEMORY_E;
00889         }
00890     }
00891 
00892     closedir(dir);
00893 
00894     return ret;
00895 }
00896 
00897 #endif /* NO_FILESYSTEM */
00898 
00899 #endif /* HAVE_CRL */
00900 #endif /* !WOLFCRYPT_ONLY */
00901