Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
crl.c
00001 /* crl.c 00002 * 00003 * Copyright (C) 2006-2013 wolfSSL Inc. 00004 * 00005 * This file is part of CyaSSL. 00006 * 00007 * CyaSSL 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 * CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00020 */ 00021 00022 #ifdef HAVE_CONFIG_H 00023 #include <config.h> 00024 #endif 00025 00026 #include <cyassl/ctaocrypt/settings.h> 00027 00028 #ifdef HAVE_CRL 00029 00030 #include <cyassl/internal.h> 00031 #include <cyassl/error-ssl.h> 00032 00033 #include <dirent.h> 00034 #include <sys/stat.h> 00035 #include <string.h> 00036 00037 00038 /* Initialze CRL members */ 00039 int InitCRL(CYASSL_CRL* crl, CYASSL_CERT_MANAGER* cm) 00040 { 00041 CYASSL_ENTER("InitCRL"); 00042 00043 crl->cm = cm; 00044 crl->crlList = NULL; 00045 crl->monitors[0].path = NULL; 00046 crl->monitors[1].path = NULL; 00047 #ifdef HAVE_CRL_MONITOR 00048 crl->tid = 0; 00049 #endif 00050 if (InitMutex(&crl->crlLock) != 0) 00051 return BAD_MUTEX_E; 00052 00053 return 0; 00054 } 00055 00056 00057 /* Initialze CRL Entry */ 00058 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl) 00059 { 00060 CYASSL_ENTER("InitCRL_Entry"); 00061 00062 XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE); 00063 /* XMEMCPY(crle->crlHash, dcrl->crlHash, SHA_DIGEST_SIZE); 00064 * copy the hash here if needed for optimized comparisons */ 00065 XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE); 00066 XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE); 00067 crle->lastDateFormat = dcrl->lastDateFormat; 00068 crle->nextDateFormat = dcrl->nextDateFormat; 00069 00070 crle->certs = dcrl->certs; /* take ownsership */ 00071 dcrl->certs = NULL; 00072 crle->totalCerts = dcrl->totalCerts; 00073 00074 return 0; 00075 } 00076 00077 00078 /* Free all CRL Entry resources */ 00079 static void FreeCRL_Entry(CRL_Entry* crle) 00080 { 00081 RevokedCert* tmp = crle->certs; 00082 00083 CYASSL_ENTER("FreeCRL_Entry"); 00084 00085 while(tmp) { 00086 RevokedCert* next = tmp->next; 00087 XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED); 00088 tmp = next; 00089 } 00090 } 00091 00092 00093 00094 /* Free all CRL resources */ 00095 void FreeCRL(CYASSL_CRL* crl, int dynamic) 00096 { 00097 CRL_Entry* tmp = crl->crlList; 00098 00099 CYASSL_ENTER("FreeCRL"); 00100 00101 if (crl->monitors[0].path) 00102 XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); 00103 00104 if (crl->monitors[1].path) 00105 XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR); 00106 00107 while(tmp) { 00108 CRL_Entry* next = tmp->next; 00109 FreeCRL_Entry(tmp); 00110 XFREE(tmp, NULL, DYNAMIC_TYPE_CRL_ENTRY); 00111 tmp = next; 00112 } 00113 00114 #ifdef HAVE_CRL_MONITOR 00115 if (crl->tid != 0) { 00116 CYASSL_MSG("Canceling monitor thread"); 00117 pthread_cancel(crl->tid); 00118 } 00119 #endif 00120 FreeMutex(&crl->crlLock); 00121 if (dynamic) /* free self */ 00122 XFREE(crl, NULL, DYNAMIC_TYPE_CRL); 00123 } 00124 00125 00126 /* Is the cert ok with CRL, return 0 on success */ 00127 int CheckCertCRL(CYASSL_CRL* crl, DecodedCert* cert) 00128 { 00129 CRL_Entry* crle; 00130 int foundEntry = 0; 00131 int ret = 0; 00132 00133 CYASSL_ENTER("CheckCertCRL"); 00134 00135 if (LockMutex(&crl->crlLock) != 0) { 00136 CYASSL_MSG("LockMutex failed"); 00137 return BAD_MUTEX_E; 00138 } 00139 00140 crle = crl->crlList; 00141 00142 while (crle) { 00143 if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) { 00144 CYASSL_MSG("Found CRL Entry on list"); 00145 CYASSL_MSG("Checking next date validity"); 00146 00147 if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) { 00148 CYASSL_MSG("CRL next date is no longer valid"); 00149 ret = ASN_AFTER_DATE_E; 00150 } 00151 else 00152 foundEntry = 1; 00153 break; 00154 } 00155 crle = crle->next; 00156 } 00157 00158 if (foundEntry) { 00159 RevokedCert* rc = crle->certs; 00160 00161 while (rc) { 00162 if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { 00163 CYASSL_MSG("Cert revoked"); 00164 ret = CRL_CERT_REVOKED; 00165 break; 00166 } 00167 rc = rc->next; 00168 } 00169 } 00170 00171 UnLockMutex(&crl->crlLock); 00172 00173 if (foundEntry == 0) { 00174 CYASSL_MSG("Couldn't find CRL for status check"); 00175 ret = CRL_MISSING; 00176 if (crl->cm->cbMissingCRL) { 00177 char url[256]; 00178 00179 CYASSL_MSG("Issuing missing CRL callback"); 00180 url[0] = '\0'; 00181 if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { 00182 XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); 00183 url[cert->extCrlInfoSz] = '\0'; 00184 } 00185 else { 00186 CYASSL_MSG("CRL url too long"); 00187 } 00188 crl->cm->cbMissingCRL(url); 00189 } 00190 } 00191 00192 00193 return ret; 00194 } 00195 00196 00197 /* Add Decoded CRL, 0 on success */ 00198 static int AddCRL(CYASSL_CRL* crl, DecodedCRL* dcrl) 00199 { 00200 CRL_Entry* crle; 00201 00202 CYASSL_ENTER("AddCRL"); 00203 00204 crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY); 00205 if (crle == NULL) { 00206 CYASSL_MSG("alloc CRL Entry failed"); 00207 return -1; 00208 } 00209 00210 if (InitCRL_Entry(crle, dcrl) < 0) { 00211 CYASSL_MSG("Init CRL Entry failed"); 00212 XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); 00213 return -1; 00214 } 00215 00216 if (LockMutex(&crl->crlLock) != 0) { 00217 CYASSL_MSG("LockMutex failed"); 00218 FreeCRL_Entry(crle); 00219 XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY); 00220 return BAD_MUTEX_E; 00221 } 00222 crle->next = crl->crlList; 00223 crl->crlList = crle; 00224 UnLockMutex(&crl->crlLock); 00225 00226 return 0; 00227 } 00228 00229 00230 /* Load CRL File of type, SSL_SUCCESS on ok */ 00231 int BufferLoadCRL(CYASSL_CRL* crl, const byte* buff, long sz, int type) 00232 { 00233 int ret = SSL_SUCCESS; 00234 const byte* myBuffer = buff; /* if DER ok, otherwise switch */ 00235 buffer der; 00236 DecodedCRL dcrl; 00237 00238 der.buffer = NULL; 00239 00240 CYASSL_ENTER("BufferLoadCRL"); 00241 00242 if (crl == NULL || buff == NULL || sz == 0) 00243 return BAD_FUNC_ARG; 00244 00245 if (type == SSL_FILETYPE_PEM) { 00246 int eccKey = 0; /* not used */ 00247 EncryptedInfo info; 00248 info.ctx = NULL; 00249 00250 ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey); 00251 if (ret == 0) { 00252 myBuffer = der.buffer; 00253 sz = der.length; 00254 } 00255 else { 00256 CYASSL_MSG("Pem to Der failed"); 00257 return -1; 00258 } 00259 } 00260 00261 InitDecodedCRL(&dcrl); 00262 ret = ParseCRL(&dcrl, myBuffer, (word32)sz, crl->cm); 00263 if (ret != 0) { 00264 CYASSL_MSG("ParseCRL error"); 00265 } 00266 else { 00267 ret = AddCRL(crl, &dcrl); 00268 if (ret != 0) { 00269 CYASSL_MSG("AddCRL error"); 00270 } 00271 } 00272 FreeDecodedCRL(&dcrl); 00273 00274 if (der.buffer) 00275 XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL); 00276 00277 if (ret == 0) 00278 return SSL_SUCCESS; /* convert */ 00279 return ret; 00280 } 00281 00282 00283 #ifdef HAVE_CRL_MONITOR 00284 00285 00286 /* read in new CRL entries and save new list */ 00287 static int SwapLists(CYASSL_CRL* crl) 00288 { 00289 int ret; 00290 CYASSL_CRL tmp; 00291 CRL_Entry* newList; 00292 00293 if (InitCRL(&tmp, crl->cm) < 0) { 00294 CYASSL_MSG("Init tmp CRL failed"); 00295 return -1; 00296 } 00297 00298 if (crl->monitors[0].path) { 00299 ret = LoadCRL(&tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0); 00300 if (ret != SSL_SUCCESS) { 00301 CYASSL_MSG("PEM LoadCRL on dir change failed"); 00302 FreeCRL(&tmp, 0); 00303 return -1; 00304 } 00305 } 00306 00307 if (crl->monitors[1].path) { 00308 ret = LoadCRL(&tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0); 00309 if (ret != SSL_SUCCESS) { 00310 CYASSL_MSG("DER LoadCRL on dir change failed"); 00311 FreeCRL(&tmp, 0); 00312 return -1; 00313 } 00314 } 00315 00316 if (LockMutex(&crl->crlLock) != 0) { 00317 CYASSL_MSG("LockMutex failed"); 00318 FreeCRL(&tmp, 0); 00319 return -1; 00320 } 00321 00322 newList = tmp.crlList; 00323 00324 /* swap lists */ 00325 tmp.crlList = crl->crlList; 00326 crl->crlList = newList; 00327 00328 UnLockMutex(&crl->crlLock); 00329 00330 FreeCRL(&tmp, 0); 00331 00332 return 0; 00333 } 00334 00335 00336 #if (defined(__MACH__) || defined(__FreeBSD__)) 00337 00338 #include <sys/types.h> 00339 #include <sys/event.h> 00340 #include <sys/time.h> 00341 #include <fcntl.h> 00342 00343 #ifdef __MACH__ 00344 #define XEVENT_MODE O_EVTONLY 00345 #elif defined(__FreeBSD__) 00346 #define XEVENT_MODE EVFILT_VNODE 00347 #endif 00348 00349 00350 /* OS X monitoring */ 00351 static void* DoMonitor(void* arg) 00352 { 00353 int fPEM, fDER, kq; 00354 struct kevent change; 00355 00356 CYASSL_CRL* crl = (CYASSL_CRL*)arg; 00357 00358 CYASSL_ENTER("DoMonitor"); 00359 00360 kq = kqueue(); 00361 if (kq == -1) { 00362 CYASSL_MSG("kqueue failed"); 00363 return NULL; 00364 } 00365 00366 fPEM = -1; 00367 fDER = -1; 00368 00369 if (crl->monitors[0].path) { 00370 fPEM = open(crl->monitors[0].path, XEVENT_MODE); 00371 if (fPEM == -1) { 00372 CYASSL_MSG("PEM event dir open failed"); 00373 return NULL; 00374 } 00375 } 00376 00377 if (crl->monitors[1].path) { 00378 fDER = open(crl->monitors[1].path, XEVENT_MODE); 00379 if (fDER == -1) { 00380 CYASSL_MSG("DER event dir open failed"); 00381 return NULL; 00382 } 00383 } 00384 00385 if (fPEM != -1) 00386 EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, 00387 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); 00388 00389 if (fDER != -1) 00390 EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, 00391 NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); 00392 00393 for (;;) { 00394 struct kevent event; 00395 int numEvents = kevent(kq, &change, 1, &event, 1, NULL); 00396 00397 CYASSL_MSG("Got kevent"); 00398 00399 if (numEvents == -1) { 00400 CYASSL_MSG("kevent problem, continue"); 00401 continue; 00402 } 00403 00404 if (SwapLists(crl) < 0) { 00405 CYASSL_MSG("SwapLists problem, continue"); 00406 } 00407 } 00408 00409 return NULL; 00410 } 00411 00412 00413 #elif defined(__linux__) 00414 00415 #include <sys/types.h> 00416 #include <sys/inotify.h> 00417 #include <unistd.h> 00418 00419 /* linux monitoring */ 00420 static void* DoMonitor(void* arg) 00421 { 00422 int notifyFd; 00423 int wd; 00424 CYASSL_CRL* crl = (CYASSL_CRL*)arg; 00425 00426 CYASSL_ENTER("DoMonitor"); 00427 00428 notifyFd = inotify_init(); 00429 if (notifyFd < 0) { 00430 CYASSL_MSG("inotify failed"); 00431 return NULL; 00432 } 00433 00434 if (crl->monitors[0].path) { 00435 wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE | 00436 IN_DELETE); 00437 if (wd < 0) { 00438 CYASSL_MSG("PEM notify add watch failed"); 00439 return NULL; 00440 } 00441 } 00442 00443 if (crl->monitors[1].path) { 00444 wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE | 00445 IN_DELETE); 00446 if (wd < 0) { 00447 CYASSL_MSG("DER notify add watch failed"); 00448 return NULL; 00449 } 00450 } 00451 00452 for (;;) { 00453 char buff[8192]; 00454 int length = read(notifyFd, buff, sizeof(buff)); 00455 00456 CYASSL_MSG("Got notify event"); 00457 00458 if (length < 0) { 00459 CYASSL_MSG("notify read problem, continue"); 00460 continue; 00461 } 00462 00463 if (SwapLists(crl) < 0) { 00464 CYASSL_MSG("SwapLists problem, continue"); 00465 } 00466 } 00467 00468 return NULL; 00469 } 00470 00471 00472 #else 00473 00474 #error "CRL monitor only currently supported on linux or mach" 00475 00476 #endif /* MACH or linux */ 00477 00478 00479 /* Start Monitoring the CRL path(s) in a thread */ 00480 static int StartMonitorCRL(CYASSL_CRL* crl) 00481 { 00482 pthread_attr_t attr; 00483 00484 CYASSL_ENTER("StartMonitorCRL"); 00485 00486 if (crl == NULL) 00487 return BAD_FUNC_ARG; 00488 00489 if (crl->tid != 0) { 00490 CYASSL_MSG("Monitor thread already running"); 00491 return MONITOR_RUNNING_E; 00492 } 00493 00494 pthread_attr_init(&attr); 00495 00496 if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) { 00497 CYASSL_MSG("Thread creation error"); 00498 return THREAD_CREATE_E; 00499 } 00500 00501 return SSL_SUCCESS; 00502 } 00503 00504 00505 #else /* HAVE_CRL_MONITOR */ 00506 00507 static int StartMonitorCRL(CYASSL_CRL* crl) 00508 { 00509 (void)crl; 00510 00511 CYASSL_ENTER("StartMonitorCRL"); 00512 CYASSL_MSG("Not compiled in"); 00513 00514 return NOT_COMPILED_IN; 00515 } 00516 00517 #endif /* HAVE_CRL_MONITOR */ 00518 00519 00520 /* Load CRL path files of type, SSL_SUCCESS on ok */ 00521 int LoadCRL(CYASSL_CRL* crl, const char* path, int type, int monitor) 00522 { 00523 struct dirent* entry; 00524 DIR* dir; 00525 int ret = SSL_SUCCESS; 00526 00527 CYASSL_ENTER("LoadCRL"); 00528 if (crl == NULL) 00529 return BAD_FUNC_ARG; 00530 00531 dir = opendir(path); 00532 if (dir == NULL) { 00533 CYASSL_MSG("opendir path crl load failed"); 00534 return BAD_PATH_ERROR; 00535 } 00536 while ( (entry = readdir(dir)) != NULL) { 00537 char name[MAX_FILENAME_SZ]; 00538 struct stat s; 00539 00540 XMEMSET(name, 0, sizeof(name)); 00541 XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2); 00542 XSTRNCAT(name, "/", 1); 00543 XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2); 00544 00545 if (stat(name, &s) != 0) { 00546 CYASSL_MSG("stat on name failed"); 00547 continue; 00548 } 00549 if (s.st_mode & S_IFREG) { 00550 00551 if (type == SSL_FILETYPE_PEM) { 00552 if (strstr(entry->d_name, ".pem") == NULL) { 00553 CYASSL_MSG("not .pem file, skipping"); 00554 continue; 00555 } 00556 } 00557 else { 00558 if (strstr(entry->d_name, ".der") == NULL && 00559 strstr(entry->d_name, ".crl") == NULL) { 00560 00561 CYASSL_MSG("not .der or .crl file, skipping"); 00562 continue; 00563 } 00564 } 00565 00566 if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) 00567 != SSL_SUCCESS) { 00568 CYASSL_MSG("CRL file load failed, continuing"); 00569 } 00570 } 00571 } 00572 00573 if (monitor & CYASSL_CRL_MONITOR) { 00574 CYASSL_MSG("monitor path requested"); 00575 00576 if (type == SSL_FILETYPE_PEM) { 00577 crl->monitors[0].path = strdup(path); 00578 crl->monitors[0].type = SSL_FILETYPE_PEM; 00579 if (crl->monitors[0].path == NULL) 00580 ret = MEMORY_E; 00581 } else { 00582 crl->monitors[1].path = strdup(path); 00583 crl->monitors[1].type = SSL_FILETYPE_ASN1; 00584 if (crl->monitors[1].path == NULL) 00585 ret = MEMORY_E; 00586 } 00587 00588 if (monitor & CYASSL_CRL_START_MON) { 00589 CYASSL_MSG("start monitoring requested"); 00590 00591 ret = StartMonitorCRL(crl); 00592 } 00593 } 00594 00595 closedir(dir); 00596 00597 return ret; 00598 } 00599 00600 #endif /* HAVE_CRL */
Generated on Tue Jul 12 2022 20:12:50 by
