]> WPIA git - cassiopeia.git/blob - src/main.cpp
add: sample communication over serial line
[cassiopeia.git] / src / main.cpp
1 #include <sys/stat.h>
2 #include <unistd.h>
3
4 #include <iostream>
5 #include <fstream>
6 #include <streambuf>
7
8 #include "database.h"
9 #include "mysql.h"
10 #include "simpleOpensslSigner.h"
11 #include "util.h"
12
13 #ifdef NO_DAEMON
14 #define DAEMON false
15 #else
16 #define DAEMON true
17 #endif
18
19 std::string keyDir;
20 std::vector<Profile> profiles;
21 std::string sqlHost, sqlUser, sqlPass, sqlDB;
22
23 std::string writeBackFile( uint32_t serial, std::string cert ) {
24     std::string filename = "keys";
25     mkdir( filename.c_str(), 0755 );
26     filename += "/crt";
27     mkdir( filename.c_str(), 0755 );
28     filename += "/" + std::to_string( serial / 1000 );
29     mkdir( filename.c_str(), 0755 );
30     filename += "/" + std::to_string( serial ) + ".crt";
31     writeFile( filename, cert );
32     std::cout << "wrote to " << filename << std::endl;
33     return filename;
34 }
35
36 int handlermain( int argc, const char* argv[] );
37
38 int main( int argc, const char* argv[] ) {
39     ( void ) argc;
40     ( void ) argv;
41     bool once = false;
42
43     if( argc == 2 && std::string( "--once" ) == std::string( argv[1] ) ) {
44         once = true;
45     }
46
47     std::ifstream config;
48
49     if( DAEMON ) {
50         config.open( "/etc/cacert/cassiopeia/cassiopeia.conf" );
51     } else {
52         config.open( "config.txt" );
53     }
54
55     if( !config.is_open() ) {
56         std::cerr << "config missing" << std::endl;
57         return 1;
58     }
59
60     std::string line1;
61
62     while( config >> line1 ) {
63         if( line1[0] == '#' ) {
64             continue;
65         }
66
67         int splitter = line1.find( "=" );
68
69         if( splitter == -1 ) {
70             std::cerr << "Ignoring malformed config line: " << line1 << std::endl;
71             continue;
72         }
73
74         std::string key = line1.substr( 0, splitter );
75         std::string value = line1.substr( splitter + 1 );
76
77         if( key == "key.directory" ) {
78             keyDir = value;
79             continue;
80         } else if( key == "sql.host" ) {
81             sqlHost = value;
82         } else if( key == "sql.user" ) {
83             sqlUser = value;
84         } else if( key == "sql.password" ) {
85             sqlPass = value;
86         } else if( key == "sql.database" ) {
87             sqlDB = value;
88         }
89
90         if( key.compare( 0, 8, "profile." ) == 0 ) {
91             int numE = key.find( ".", 9 );
92
93             if( numE == 0 ) {
94                 std::cout << "invalid line: " << line1 << std::endl;
95                 continue;
96             }
97
98             unsigned int i = atoi( key.substr( 8, numE - 8 ).c_str() );
99             std::string rest = key.substr( numE + 1 );
100
101             if( i + 1 > profiles.size() ) {
102                 profiles.resize( i + 1 );
103             }
104
105             if( rest == "key" ) {
106                 profiles[i].key = value;
107             } else if( rest == "cert" ) {
108                 profiles[i].cert = value;
109             } else {
110                 std::cout << "invalid line: " << line1 << std::endl;
111                 continue;
112             }
113         }
114     }
115
116     std::cout << profiles.size() << " profiles loaded." << std::endl;
117
118     if( keyDir == "" ) {
119         std::cerr << "Missing config property key.directory" << std::endl;
120         return -1;
121     }
122
123     config.close();
124     return handlermain( argc, argv );
125
126     std::shared_ptr<JobProvider> jp( new MySQLJobProvider( sqlHost, sqlUser, sqlPass, sqlDB ) );
127     std::shared_ptr<Signer> sign( new SimpleOpensslSigner() );
128
129     while( true ) {
130         std::shared_ptr<Job> job = jp->fetchJob();
131
132         if( !job ) {
133             std::cout << "Nothing to work on" << std::endl;
134             sleep( 5 );
135             continue;
136         }
137
138         if( job->task == "sign" ) {
139             try {
140                 std::shared_ptr<TBSCertificate> cert = jp->fetchTBSCert( job );
141
142                 if( !cert ) {
143                     std::cout << "wasn't able to load CSR" << std::endl;
144                     return 2;
145                 }
146
147                 std::cout << "Found a CSR at '" << cert->csr << "' signing" << std::endl;
148                 cert->csr_content = readFile( cert->csr );
149
150                 std::shared_ptr<SignedCertificate> res = sign->sign( cert );
151                 std::string fn = writeBackFile( atoi( job->target.c_str() ), res->certificate );
152                 res->crt_name = fn;
153                 jp->writeBack( job, res );
154             } catch( const char* c ) {
155                 std::cerr << "ERROR: " << c << std::endl;
156                 return 2;
157             } catch( std::string c ) {
158                 std::cerr << "ERROR: " << c << std::endl;
159                 return 2;
160             }
161         } else {
162             std::cout << "Unknown job type" << job->task << std::endl;
163         }
164
165         if( DAEMON && !jp->finishJob( job ) ) {
166             return 1;
167         }
168
169         if( !DAEMON || once ) {
170             return 0;
171         }
172     }
173 }