]> WPIA git - cassiopeia.git/blob - src/config.cpp
add: handle the 'noOCSP' feature in the include section
[cassiopeia.git] / src / config.cpp
1 #include <iostream>
2 #include <vector>
3 #include <fstream>
4 #include <dirent.h>
5 #include <unordered_map>
6
7 #include "crypto/sslUtil.h"
8
9 #include "log/logger.hpp"
10
11 std::string keyDir;
12 std::unordered_map<std::string, Profile> profiles;
13 std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
14 std::string sqlHost, sqlUser, sqlPass, sqlDB;
15 std::string serialPath;
16 std::string crlPrefix;
17 std::string crtPrefix;
18 std::string ocspPath;
19
20 std::shared_ptr<std::unordered_map<std::string, std::string>> parseConf( std::string path ) {
21     auto map = std::make_shared<std::unordered_map<std::string, std::string>>();
22     std::ifstream config;
23     config.open( path );
24
25     if( !config.is_open() ) {
26         logger::notef( "Where is \"%s\"?", path );
27         throw std::runtime_error( "Config missing" );
28     }
29
30     std::string line1;
31
32     while( std::getline( config, line1 ) ) {
33         if( line1[0] == '#' || line1.size() == 0 ) {
34             continue;
35         }
36
37         int splitter = line1.find( "=" );
38
39         if( splitter == -1 ) {
40             logger::warn( "Ignoring malformed config line: ", line1 );
41             continue;
42         }
43
44         std::string key = line1.substr( 0, splitter );
45         std::string value = line1.substr( splitter + 1 );
46         map->emplace( key, value );
47     }
48
49     config.close();
50
51     return map;
52 }
53
54 int parseProfiles() {
55     CAs = std::unordered_map<std::string, std::shared_ptr<CAConfig>>();
56
57     DIR *dp;
58     struct dirent *ep;
59     dp = opendir( "profiles" );
60
61     if( dp == NULL ) {
62         logger::error( "Profiles directory not found" );
63         return -1;
64     }
65
66     while( ( ep = readdir( dp ) ) ) {
67         if( ep->d_name[0] == '.' ) {
68             continue;
69         }
70
71         std::string profileName( ep->d_name );
72
73         int splitter = profileName.find( "-" );
74
75         if( splitter == -1 ) {
76             logger::warn( "Ignoring malformed profile: ", profileName );
77             continue;
78         }
79
80         std::string id = profileName.substr( 0, splitter );
81
82         if( profileName.substr( profileName.size() - 4 ) != ".cfg" ) {
83             logger::warn( "Ignoring malformed profile: ", profileName );
84             continue;
85         }
86
87         auto map = parseConf( std::string( "profiles/" ) + profileName );
88
89         profileName = profileName.substr( 0, profileName.size() - 4 );
90
91         Profile prof;
92         prof.id = std::stoi( id );
93         prof.eku = map->at( "eku" );
94         prof.ku = map->at( "ku" );
95         {
96             std::string include = map->at( "include" );
97             size_t pos = 0;
98             size_t end = 0;
99             std::unordered_set<std::string> include_set;
100
101             while( ( end = include.find( ",", pos ) ) != std::string::npos ) {
102                 include_set.emplace( include.substr( pos, end - pos ) );
103                 pos = end + 1;
104             }
105
106             include_set.emplace( include.substr( pos ) );
107             prof.include = include_set;
108         }
109         prof.maxValidity = std::stoi( map->at( "days" ) ) * /* DAYS */24 * 60 * 60;
110
111
112         DIR *dir;
113         struct dirent *ent;
114
115         if( profileName == "0100-ocsp" ) {
116             //This profile does not have a specific CA. The concrete CA has to be set in each request.
117         } else if( ( dir = opendir( "ca" ) ) != NULL ) {
118             std::string cas = map->at( "ca" );
119             std::string toFind = cas + "_";
120
121             while( ( ent = readdir( dir ) ) != NULL ) {
122                 std::string caName = std::string( ent->d_name );
123
124                 if( caName.find( toFind ) != 0 ) {
125                     continue;
126                 }
127
128                 if( CAs.find( caName ) == CAs.end() ) {
129                     auto ca = std::make_shared<CAConfig>( caName );
130                     CAs.emplace( caName, ca );
131                 }
132
133                 prof.ca.push_back( CAs.at( caName ) );
134                 logger::note( "Adding CA: ", caName );
135             }
136
137             closedir( dir );
138         } else {
139             throw std::runtime_error( "Directory with CAConfigs not found" );
140         }
141
142         profiles.emplace( profileName, prof );
143         logger::notef( "Profile: \"%s\" up and running.", profileName );
144     }
145
146     ( void ) closedir( dp );
147
148     logger::notef( "%s profiles loaded.", profiles.size() );
149
150     return 0;
151 }
152
153 int parseConfig( std::string path ) {
154     auto masterConf = parseConf( path );
155
156     keyDir = masterConf->at( "key.directory" );
157     sqlHost = masterConf->at( "sql.host" );
158     sqlUser = masterConf->at( "sql.user" );
159     sqlPass = masterConf->at( "sql.password" );
160     sqlDB = masterConf->at( "sql.database" );
161     serialPath = masterConf->at( "serialPath" );
162     crlPrefix = masterConf->at( "crlPrefix" );
163     crtPrefix = masterConf->at( "crtPrefix" );
164
165     auto ocspPathEntry = masterConf->find( "ocsp.path" );
166
167     if( ocspPathEntry == masterConf->end() ) {
168         ocspPath = "";
169     } else {
170         ocspPath = ocspPathEntry->second;
171     }
172
173     if( keyDir == "" ) {
174         logger::error( "Missing config property key.directory" );
175         return -1;
176     }
177
178     if( parseProfiles() != 0 ) {
179         return -1;
180     }
181
182     return 0;
183 }