| 743 | |
| 744 | |
| 745 | int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file, |
| 746 | const char* path) |
| 747 | { |
| 748 | int ret = SSL_FAILURE; |
| 749 | const int HALF_PATH = 128; |
| 750 | |
| 751 | if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA); |
| 752 | |
| 753 | if (ret == SSL_SUCCESS && path) { |
| 754 | // call read_file for each reqular file in path |
| 755 | #ifdef _WIN32 |
| 756 | |
| 757 | WIN32_FIND_DATA FindFileData; |
| 758 | HANDLE hFind; |
| 759 | |
| 760 | char name[MAX_PATH + 1]; // directory specification |
| 761 | strncpy(name, path, MAX_PATH - 3); |
| 762 | strncat(name, "\\*", 3); |
| 763 | |
| 764 | hFind = FindFirstFile(name, &FindFileData); |
| 765 | if (hFind == INVALID_HANDLE_VALUE) return SSL_BAD_PATH; |
| 766 | |
| 767 | do { |
| 768 | if (FindFileData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) { |
| 769 | strncpy(name, path, MAX_PATH - 2 - HALF_PATH); |
| 770 | strncat(name, "\\", 2); |
| 771 | strncat(name, FindFileData.cFileName, HALF_PATH); |
| 772 | ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA); |
| 773 | } |
| 774 | } while (ret == SSL_SUCCESS && FindNextFile(hFind, &FindFileData)); |
| 775 | |
| 776 | FindClose(hFind); |
| 777 | |
| 778 | #else // _WIN32 |
| 779 | |
| 780 | const int MAX_PATH = 260; |
| 781 | |
| 782 | DIR* dir = opendir(path); |
| 783 | if (!dir) return SSL_BAD_PATH; |
| 784 | |
| 785 | struct dirent* entry; |
| 786 | struct stat buf; |
| 787 | char name[MAX_PATH + 1]; |
| 788 | |
| 789 | while (ret == SSL_SUCCESS && (entry = readdir(dir))) { |
| 790 | strncpy(name, path, MAX_PATH - 1 - HALF_PATH); |
| 791 | strncat(name, "/", 1); |
| 792 | strncat(name, entry->d_name, HALF_PATH); |
| 793 | if (stat(name, &buf) < 0) { |
| 794 | closedir(dir); |
| 795 | return SSL_BAD_STAT; |
| 796 | } |
| 797 | |
| 798 | if (S_ISREG(buf.st_mode)) |
| 799 | ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA); |
| 800 | } |
| 801 | |
| 802 | closedir(dir); |