]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/src/crl.c
Update WolfSSL library to the latest version.
[freertos] / FreeRTOS-Plus / Source / WolfSSL / src / crl.c
1 /* crl.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22   /* Name change compatibility layer no longer needs included here */
23
24 #ifdef HAVE_CONFIG_H
25     #include <config.h>
26 #endif
27
28 #include <wolfssl/wolfcrypt/settings.h>
29
30 #ifdef HAVE_CRL
31
32 #include <wolfssl/internal.h>
33 #include <wolfssl/error-ssl.h>
34
35 #include <dirent.h>
36 #include <sys/stat.h>
37 #include <string.h>
38
39 #ifdef HAVE_CRL_MONITOR
40     static int StopMonitor(int mfd);
41 #endif
42
43
44 /* Initialze CRL members */
45 int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm)
46 {
47     WOLFSSL_ENTER("InitCRL");
48
49     crl->cm = cm;
50     crl->crlList = NULL;
51     crl->monitors[0].path = NULL;
52     crl->monitors[1].path = NULL;
53 #ifdef HAVE_CRL_MONITOR
54     crl->tid =  0;
55     crl->mfd = -1;   /* mfd for bsd is kqueue fd, eventfd for linux */
56 #endif
57     if (InitMutex(&crl->crlLock) != 0)
58         return BAD_MUTEX_E; 
59
60     return 0;
61 }
62
63
64 /* Initialze CRL Entry */
65 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl)
66 {
67     WOLFSSL_ENTER("InitCRL_Entry");
68
69     XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE);
70     /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE);
71      *   copy the hash here if needed for optimized comparisons */
72     XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
73     XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
74     crle->lastDateFormat = dcrl->lastDateFormat;
75     crle->nextDateFormat = dcrl->nextDateFormat;
76
77     crle->certs = dcrl->certs;   /* take ownsership */
78     dcrl->certs = NULL;
79     crle->totalCerts = dcrl->totalCerts;
80
81     return 0;
82 }
83
84
85 /* Free all CRL Entry resources */
86 static void FreeCRL_Entry(CRL_Entry* crle)
87 {
88     RevokedCert* tmp = crle->certs; 
89
90     WOLFSSL_ENTER("FreeCRL_Entry");
91
92     while(tmp) {
93         RevokedCert* next = tmp->next;
94         XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
95         tmp = next;
96     }
97 }
98
99
100
101 /* Free all CRL resources */
102 void FreeCRL(WOLFSSL_CRL* crl, int dynamic)
103 {
104     CRL_Entry* tmp = crl->crlList;
105
106     WOLFSSL_ENTER("FreeCRL");
107
108     if (crl->monitors[0].path)
109         XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
110
111     if (crl->monitors[1].path)
112         XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
113
114     while(tmp) {
115         CRL_Entry* next = tmp->next;
116         FreeCRL_Entry(tmp);
117         XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY);
118         tmp = next;
119     }   
120
121 #ifdef HAVE_CRL_MONITOR
122     if (crl->tid != 0) {
123         WOLFSSL_MSG("stopping monitor thread");
124         if (StopMonitor(crl->mfd) == 0)
125             pthread_join(crl->tid, NULL);
126         else {
127             WOLFSSL_MSG("stop monitor failed, cancel instead");
128             pthread_cancel(crl->tid);
129         }
130     }
131 #endif
132     FreeMutex(&crl->crlLock);
133     if (dynamic)   /* free self */
134         XFREE(crl, NULL, DYNAMIC_TYPE_CRL);
135 }
136
137
138 /* Is the cert ok with CRL, return 0 on success */
139 int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert)
140 {
141     CRL_Entry* crle;
142     int        foundEntry = 0;
143     int        ret = 0;
144
145     WOLFSSL_ENTER("CheckCertCRL");
146
147     if (LockMutex(&crl->crlLock) != 0) {
148         WOLFSSL_MSG("LockMutex failed");
149         return BAD_MUTEX_E;
150     }
151
152     crle = crl->crlList;
153
154     while (crle) {
155         if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) {
156             WOLFSSL_MSG("Found CRL Entry on list");
157             WOLFSSL_MSG("Checking next date validity");
158
159             if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) {
160                 WOLFSSL_MSG("CRL next date is no longer valid");
161                 ret = ASN_AFTER_DATE_E;
162             }
163             else
164                 foundEntry = 1;
165             break;
166         }
167         crle = crle->next;
168     }
169
170     if (foundEntry) {
171         RevokedCert* rc = crle->certs;
172
173         while (rc) {
174             if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
175                 WOLFSSL_MSG("Cert revoked");
176                 ret = CRL_CERT_REVOKED;
177                 break;
178             }
179             rc = rc->next;      
180         }
181     }
182
183     UnLockMutex(&crl->crlLock);
184
185     if (foundEntry == 0) {
186         WOLFSSL_MSG("Couldn't find CRL for status check");
187         ret = CRL_MISSING;
188         if (crl->cm->cbMissingCRL) {
189             char url[256];
190
191             WOLFSSL_MSG("Issuing missing CRL callback");
192             url[0] = '\0';
193             if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
194                 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
195                 url[cert->extCrlInfoSz] = '\0';
196             }
197             else  {
198                 WOLFSSL_MSG("CRL url too long");
199             }
200             crl->cm->cbMissingCRL(url);
201         }
202     }
203
204
205     return ret; 
206 }
207
208
209 /* Add Decoded CRL, 0 on success */
210 static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl)
211 {
212     CRL_Entry* crle;
213
214     WOLFSSL_ENTER("AddCRL");
215
216     crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
217     if (crle == NULL) {
218         WOLFSSL_MSG("alloc CRL Entry failed");
219         return -1;
220     }
221
222     if (InitCRL_Entry(crle, dcrl) < 0) {
223         WOLFSSL_MSG("Init CRL Entry failed");
224         XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
225         return -1;
226     }
227
228     if (LockMutex(&crl->crlLock) != 0) {
229         WOLFSSL_MSG("LockMutex failed");
230         FreeCRL_Entry(crle);
231         XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
232         return BAD_MUTEX_E;
233     }
234     crle->next = crl->crlList;
235     crl->crlList = crle;
236     UnLockMutex(&crl->crlLock);
237
238     return 0;
239 }
240
241
242 /* Load CRL File of type, SSL_SUCCESS on ok */
243 int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type)
244 {
245     int          ret = SSL_SUCCESS;
246     const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
247     buffer       der;
248 #ifdef WOLFSSL_SMALL_STACK
249     DecodedCRL*  dcrl;
250 #else
251     DecodedCRL   dcrl[1];
252 #endif
253
254     der.buffer = NULL;
255
256     WOLFSSL_ENTER("BufferLoadCRL");
257
258     if (crl == NULL || buff == NULL || sz == 0)
259         return BAD_FUNC_ARG;
260
261     if (type == SSL_FILETYPE_PEM) {
262         int eccKey = 0;   /* not used */
263         EncryptedInfo info;
264         info.ctx = NULL;
265
266         ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
267         if (ret == 0) {
268             myBuffer = der.buffer;
269             sz = der.length;
270         }
271         else {
272             WOLFSSL_MSG("Pem to Der failed");
273             return -1;
274         }
275     }
276
277 #ifdef WOLFSSL_SMALL_STACK
278     dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
279     if (dcrl == NULL) {
280         if (der.buffer)
281             XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
282
283         return MEMORY_E;
284     }
285 #endif
286
287     InitDecodedCRL(dcrl);
288     ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm);
289     if (ret != 0) {
290         WOLFSSL_MSG("ParseCRL error");
291     }
292     else {
293         ret = AddCRL(crl, dcrl);
294         if (ret != 0) {
295             WOLFSSL_MSG("AddCRL error");
296         }
297     }
298
299     FreeDecodedCRL(dcrl);
300
301 #ifdef WOLFSSL_SMALL_STACK
302     XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER);
303 #endif
304
305     if (der.buffer)
306         XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
307
308     return ret ? ret : SSL_SUCCESS; /* convert 0 to SSL_SUCCESS */
309 }
310
311
312 #ifdef HAVE_CRL_MONITOR
313
314
315 /* read in new CRL entries and save new list */
316 static int SwapLists(WOLFSSL_CRL* crl)
317 {
318     int        ret;
319     CRL_Entry* newList;
320 #ifdef WOLFSSL_SMALL_STACK
321     WOLFSSL_CRL* tmp;    
322 #else
323     WOLFSSL_CRL tmp[1];
324 #endif
325     
326 #ifdef WOLFSSL_SMALL_STACK
327     tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER);
328     if (tmp == NULL)
329         return MEMORY_E;
330 #endif   
331
332     if (InitCRL(tmp, crl->cm) < 0) {
333         WOLFSSL_MSG("Init tmp CRL failed");
334 #ifdef WOLFSSL_SMALL_STACK
335         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
336 #endif
337         return -1;
338     }
339
340     if (crl->monitors[0].path) {
341         ret = LoadCRL(tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0);
342         if (ret != SSL_SUCCESS) {
343             WOLFSSL_MSG("PEM LoadCRL on dir change failed");
344             FreeCRL(tmp, 0);
345 #ifdef WOLFSSL_SMALL_STACK
346             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
347 #endif
348             return -1;
349         }
350     }
351
352     if (crl->monitors[1].path) {
353         ret = LoadCRL(tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0);
354         if (ret != SSL_SUCCESS) {
355             WOLFSSL_MSG("DER LoadCRL on dir change failed");
356             FreeCRL(tmp, 0);
357 #ifdef WOLFSSL_SMALL_STACK
358             XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
359 #endif
360             return -1;
361         }
362     }
363
364     if (LockMutex(&crl->crlLock) != 0) {
365         WOLFSSL_MSG("LockMutex failed");
366         FreeCRL(tmp, 0);
367 #ifdef WOLFSSL_SMALL_STACK
368         XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
369 #endif
370         return -1;
371     }
372
373     newList = tmp->crlList;
374
375     /* swap lists */
376     tmp->crlList  = crl->crlList;
377     crl->crlList = newList;
378
379     UnLockMutex(&crl->crlLock);
380
381     FreeCRL(tmp, 0);
382
383 #ifdef WOLFSSL_SMALL_STACK
384     XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER);
385 #endif
386
387     return 0;
388 }
389
390
391 #if (defined(__MACH__) || defined(__FreeBSD__))
392
393 #include <sys/types.h>
394 #include <sys/event.h>
395 #include <sys/time.h>
396 #include <fcntl.h>
397 #include <unistd.h>
398
399 #ifdef __MACH__
400     #define XEVENT_MODE O_EVTONLY
401 #elif defined(__FreeBSD__)
402     #define XEVENT_MODE EVFILT_VNODE
403 #endif
404
405
406 /* we need a unique kqueue user filter fd for crl in case user is doing custom
407  * events too */
408 #ifndef CRL_CUSTOM_FD
409     #define CRL_CUSTOM_FD 123456
410 #endif
411
412
413 /* shutdown monitor thread, 0 on success */
414 static int StopMonitor(int mfd)
415 {
416     struct kevent change;
417
418     /* trigger custom shutdown */
419     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL);
420     if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) {
421         WOLFSSL_MSG("kevent trigger customer event failed");
422         return -1;
423     }
424
425     return 0;
426 }
427
428
429 /* OS X  monitoring */
430 static void* DoMonitor(void* arg)
431 {
432     int fPEM, fDER;
433     struct kevent change;
434
435     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
436
437     WOLFSSL_ENTER("DoMonitor");
438
439     crl->mfd = kqueue();
440     if (crl->mfd == -1) {
441         WOLFSSL_MSG("kqueue failed");
442         return NULL;
443     }
444
445     /* listen for custom shutdown event */
446     EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL);
447     if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) {
448         WOLFSSL_MSG("kevent monitor customer event failed");
449         close(crl->mfd);
450         return NULL;
451     }
452
453     fPEM = -1;
454     fDER = -1;
455
456     if (crl->monitors[0].path) {
457         fPEM = open(crl->monitors[0].path, XEVENT_MODE);
458         if (fPEM == -1) {
459             WOLFSSL_MSG("PEM event dir open failed");
460             close(crl->mfd);
461             return NULL;
462         }
463     }
464
465     if (crl->monitors[1].path) {
466         fDER = open(crl->monitors[1].path, XEVENT_MODE);
467         if (fDER == -1) {
468             WOLFSSL_MSG("DER event dir open failed");
469             close(crl->mfd);
470             return NULL;
471         }
472     }
473
474     if (fPEM != -1)
475         EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
476                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
477
478     if (fDER != -1)
479         EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
480                 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
481
482     for (;;) {
483         struct kevent event;
484         int           numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL);
485        
486         WOLFSSL_MSG("Got kevent");
487
488         if (numEvents == -1) {
489             WOLFSSL_MSG("kevent problem, continue");
490             continue;
491         }
492
493         if (event.filter == EVFILT_USER) {
494             WOLFSSL_MSG("Got user shutdown event, breaking out");
495             break;
496         }
497
498         if (SwapLists(crl) < 0) {
499             WOLFSSL_MSG("SwapLists problem, continue");
500         }
501     }
502
503     if (fPEM != -1)
504         close(fPEM);
505     if (fDER != -1)
506         close(fDER);
507
508     close(crl->mfd);
509
510     return NULL;
511 }
512
513
514 #elif defined(__linux__)
515
516 #include <sys/types.h>
517 #include <sys/inotify.h>
518 #include <sys/eventfd.h>
519 #include <unistd.h>
520
521
522 #ifndef max
523     static INLINE int max(int a, int b)
524     {
525         return a > b ? a : b;
526     }
527 #endif /* max */
528
529
530 /* shutdown monitor thread, 0 on success */
531 static int StopMonitor(int mfd)
532 {
533     word64 w64 = 1;
534
535     /* write to our custom event */
536     if (write(mfd, &w64, sizeof(w64)) < 0) {
537         WOLFSSL_MSG("StopMonitor write failed");
538         return -1;
539     }
540
541     return 0;
542 }
543
544
545 /* linux monitoring */
546 static void* DoMonitor(void* arg)
547 {
548     int         notifyFd;
549     int         wd  = -1;
550     WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg;
551 #ifdef WOLFSSL_SMALL_STACK
552     char*       buff;
553 #else
554     char        buff[8192];
555 #endif
556
557     WOLFSSL_ENTER("DoMonitor");
558
559     crl->mfd = eventfd(0, 0);  /* our custom shutdown event */
560     if (crl->mfd < 0) {
561         WOLFSSL_MSG("eventfd failed");
562         return NULL;
563     }
564
565     notifyFd = inotify_init();
566     if (notifyFd < 0) {
567         WOLFSSL_MSG("inotify failed");
568         close(crl->mfd);
569         return NULL;
570     }
571
572     if (crl->monitors[0].path) {
573         wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
574                                                                 IN_DELETE);
575         if (wd < 0) {
576             WOLFSSL_MSG("PEM notify add watch failed");
577             close(crl->mfd);
578             close(notifyFd);
579             return NULL;
580         }
581     }
582
583     if (crl->monitors[1].path) {
584         wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
585                                                                 IN_DELETE);
586         if (wd < 0) {
587             WOLFSSL_MSG("DER notify add watch failed");
588             close(crl->mfd);
589             close(notifyFd);
590             return NULL;
591         }
592     }
593
594 #ifdef WOLFSSL_SMALL_STACK
595     buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER);
596     if (buff == NULL)
597         return NULL;
598 #endif
599
600     for (;;) {
601         fd_set readfds;
602         int    result;
603         int    length;
604
605         FD_ZERO(&readfds);
606         FD_SET(notifyFd, &readfds);
607         FD_SET(crl->mfd, &readfds);
608
609         result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL);
610        
611         WOLFSSL_MSG("Got notify event");
612
613         if (result < 0) {
614             WOLFSSL_MSG("select problem, continue");
615             continue;
616         }
617
618         if (FD_ISSET(crl->mfd, &readfds)) {
619             WOLFSSL_MSG("got custom shutdown event, breaking out");
620             break;
621         }
622
623         length = read(notifyFd, buff, 8192);
624         if (length < 0) {
625             WOLFSSL_MSG("notify read problem, continue");
626             continue;
627         } 
628
629         if (SwapLists(crl) < 0) {
630             WOLFSSL_MSG("SwapLists problem, continue");
631         }
632     }
633
634 #ifdef WOLFSSL_SMALL_STACK
635     XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER);
636 #endif
637
638     if (wd > 0)
639         inotify_rm_watch(notifyFd, wd);
640     close(crl->mfd);
641     close(notifyFd);
642
643     return NULL;
644 }
645
646
647 #else
648
649 #error "CRL monitor only currently supported on linux or mach"
650
651 #endif /* MACH or linux */
652
653
654 /* Start Monitoring the CRL path(s) in a thread */
655 static int StartMonitorCRL(WOLFSSL_CRL* crl)
656 {
657     pthread_attr_t attr;
658
659     WOLFSSL_ENTER("StartMonitorCRL");
660
661     if (crl == NULL) 
662         return BAD_FUNC_ARG;
663
664     if (crl->tid != 0) {
665         WOLFSSL_MSG("Monitor thread already running");
666         return MONITOR_RUNNING_E;
667     }
668
669     pthread_attr_init(&attr);
670
671     if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) {
672         WOLFSSL_MSG("Thread creation error");
673         return THREAD_CREATE_E;
674     }
675
676     return SSL_SUCCESS;
677 }
678
679
680 #else /* HAVE_CRL_MONITOR */
681
682 static int StartMonitorCRL(WOLFSSL_CRL* crl)
683 {
684     (void)crl;
685
686     WOLFSSL_ENTER("StartMonitorCRL");
687     WOLFSSL_MSG("Not compiled in");
688
689     return NOT_COMPILED_IN;
690 }
691
692 #endif  /* HAVE_CRL_MONITOR */
693
694
695 /* Load CRL path files of type, SSL_SUCCESS on ok */ 
696 int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor)
697 {
698     struct dirent* entry;
699     DIR*           dir;
700     int            ret = SSL_SUCCESS;
701 #ifdef WOLFSSL_SMALL_STACK
702     char*          name;
703 #else
704     char           name[MAX_FILENAME_SZ];
705 #endif
706
707     WOLFSSL_ENTER("LoadCRL");
708     if (crl == NULL)
709         return BAD_FUNC_ARG;
710
711     dir = opendir(path);
712     if (dir == NULL) {
713         WOLFSSL_MSG("opendir path crl load failed");
714         return BAD_PATH_ERROR;
715     }
716
717 #ifdef WOLFSSL_SMALL_STACK
718     name = (char*)XMALLOC(MAX_FILENAME_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
719     if (name == NULL)
720         return MEMORY_E;
721 #endif
722
723     while ( (entry = readdir(dir)) != NULL) {
724         struct stat s;
725
726         XMEMSET(name, 0, MAX_FILENAME_SZ);
727         XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
728         XSTRNCAT(name, "/", 1);
729         XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
730
731         if (stat(name, &s) != 0) {
732             WOLFSSL_MSG("stat on name failed");
733             continue;
734         }
735         if (s.st_mode & S_IFREG) {
736
737             if (type == SSL_FILETYPE_PEM) {
738                 if (strstr(entry->d_name, ".pem") == NULL) {
739                     WOLFSSL_MSG("not .pem file, skipping");
740                     continue;
741                 }
742             }
743             else {
744                 if (strstr(entry->d_name, ".der") == NULL &&
745                     strstr(entry->d_name, ".crl") == NULL) {
746
747                     WOLFSSL_MSG("not .der or .crl file, skipping");
748                     continue;
749                 }
750             }
751
752             if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
753                                                                != SSL_SUCCESS) {
754                 WOLFSSL_MSG("CRL file load failed, continuing");
755             }
756         }
757     }
758
759 #ifdef WOLFSSL_SMALL_STACK
760     XFREE(name, NULL, DYNAMIC_TYPE_TMP_BUFFER);
761 #endif
762
763     if (monitor & WOLFSSL_CRL_MONITOR) {
764         WOLFSSL_MSG("monitor path requested");
765
766         if (type == SSL_FILETYPE_PEM) {
767             crl->monitors[0].path = strdup(path);
768             crl->monitors[0].type = SSL_FILETYPE_PEM;
769             if (crl->monitors[0].path == NULL)
770                 ret = MEMORY_E;
771         } else {
772             crl->monitors[1].path = strdup(path);
773             crl->monitors[1].type = SSL_FILETYPE_ASN1;
774             if (crl->monitors[1].path == NULL)
775                 ret = MEMORY_E;
776         }
777       
778         if (monitor & WOLFSSL_CRL_START_MON) {
779             WOLFSSL_MSG("start monitoring requested");
780     
781             ret = StartMonitorCRL(crl);
782        } 
783     }
784     
785     closedir(dir);
786
787     return ret;
788 }
789
790 #endif /* HAVE_CRL */