actions: verification
This commit is contained in:
		
							parent
							
								
									fd96d76df9
								
							
						
					
					
						commit
						fc163535f5
					
				
							
								
								
									
										220
									
								
								src/actions.cpp
									
									
									
									
									
								
							
							
						
						
									
										220
									
								
								src/actions.cpp
									
									
									
									
									
								
							| 
						 | 
					@ -228,7 +228,7 @@ int action_decrypt (bool armor,
 | 
				
			||||||
	if (!kpe) {
 | 
						if (!kpe) {
 | 
				
			||||||
		err ("error: decryption privkey unavailable");
 | 
							err ("error: decryption privkey unavailable");
 | 
				
			||||||
		err ("info: requires key @" << msg.key_id);
 | 
							err ("info: requires key @" << msg.key_id);
 | 
				
			||||||
		return 1;
 | 
							return 2; //missing key flag
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//and the algorithm
 | 
						//and the algorithm
 | 
				
			||||||
| 
						 | 
					@ -404,7 +404,223 @@ int action_verify (bool armor, const std::string&detach,
 | 
				
			||||||
                   bool clearsign, bool yes,
 | 
					                   bool clearsign, bool yes,
 | 
				
			||||||
                   keyring&KR, algorithm_suite&AS)
 | 
					                   keyring&KR, algorithm_suite&AS)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return 0;
 | 
						/*
 | 
				
			||||||
 | 
						 * check flags validity, open detach if possible
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (clearsign && (detach.length() || armor) ) {
 | 
				
			||||||
 | 
							err ("error: clearsign cannot be combined "
 | 
				
			||||||
 | 
							     "with armor or detach-sign");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::ifstream detf;
 | 
				
			||||||
 | 
						if (detach.length() ) {
 | 
				
			||||||
 | 
							detf.open (detach.c_str(), std::ios::in | std::ios::binary);
 | 
				
			||||||
 | 
							if (!detf) {
 | 
				
			||||||
 | 
								err ("error: can't open detached signature file");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * read input and unpack the whole thing into message.
 | 
				
			||||||
 | 
						 * Takes a lot of effort. :)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signed_msg msg;
 | 
				
			||||||
 | 
						std::string data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						read_all_input (data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (clearsign) {
 | 
				
			||||||
 | 
							std::string type;
 | 
				
			||||||
 | 
							std::vector<std::string> parts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!envelope_read (data, 0, type, parts) ) {
 | 
				
			||||||
 | 
								err ("error: no data envelope found");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (type != ENVELOPE_CLEARSIGN || parts.size() != 2) {
 | 
				
			||||||
 | 
								err ("error: wrong envelope format");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string sig;
 | 
				
			||||||
 | 
							if (!base64_decode (parts[1], sig) ) {
 | 
				
			||||||
 | 
								err ("error: malformed data");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode*M = sencode_decode (sig);
 | 
				
			||||||
 | 
							if (!M) {
 | 
				
			||||||
 | 
								err ("error: could not parse input sencode");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!msg.unserialize (M) ) {
 | 
				
			||||||
 | 
								err ("error: could not parse input structure");
 | 
				
			||||||
 | 
								sencode_destroy (M);
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode_destroy (M);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string tmp;
 | 
				
			||||||
 | 
							if (!msg.message.to_string (tmp) || tmp != MSG_CLEARTEXT) {
 | 
				
			||||||
 | 
								err ("error: malformed cleartext signature");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg.message.from_string (parts[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else if (detach.length() ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string sig;
 | 
				
			||||||
 | 
							if (!read_all_input (sig, detf) ) {
 | 
				
			||||||
 | 
								err ("error: can't read detached signature file");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							detf.close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (armor) {
 | 
				
			||||||
 | 
								std::vector<std::string> parts;
 | 
				
			||||||
 | 
								std::string type;
 | 
				
			||||||
 | 
								if (!envelope_read (sig, 0, type, parts) ) {
 | 
				
			||||||
 | 
									err ("error: no data envelope found");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (type != ENVELOPE_DETACHSIGN || parts.size() != 1) {
 | 
				
			||||||
 | 
									err ("error: wrong envelope format");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!base64_decode (parts[0], sig) ) {
 | 
				
			||||||
 | 
									err ("error: malformed data");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode*M = sencode_decode (sig);
 | 
				
			||||||
 | 
							if (!M) {
 | 
				
			||||||
 | 
								err ("error: could not parse input sencode");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!msg.unserialize (M) ) {
 | 
				
			||||||
 | 
								err ("error: could not parse input structure");
 | 
				
			||||||
 | 
								sencode_destroy (M);
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode_destroy (M);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string tmp;
 | 
				
			||||||
 | 
							if (!msg.message.to_string (tmp) || tmp != MSG_DETACHED) {
 | 
				
			||||||
 | 
								err ("error: malformed detached signature");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msg.message.from_string (data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							//classical sig
 | 
				
			||||||
 | 
							if (armor) {
 | 
				
			||||||
 | 
								std::string type;
 | 
				
			||||||
 | 
								std::vector<std::string> parts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!envelope_read (data, 0, type, parts) ) {
 | 
				
			||||||
 | 
									err ("error: no data envelope found");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (type != ENVELOPE_SIG || parts.size() != 1) {
 | 
				
			||||||
 | 
									err ("error: wrong envelope format");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!base64_decode (parts[0], data) ) {
 | 
				
			||||||
 | 
									err ("error: malformed data");
 | 
				
			||||||
 | 
									return 1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode*M = sencode_decode (data);
 | 
				
			||||||
 | 
							if (!M) {
 | 
				
			||||||
 | 
								err ("error: could not parse input sencode");
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!msg.unserialize (M) ) {
 | 
				
			||||||
 | 
								err ("error: could not parse input structure");
 | 
				
			||||||
 | 
								sencode_destroy (M);
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sencode_destroy (M);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//check that the message can be converted to bytes
 | 
				
			||||||
 | 
						if (msg.message.size() & 0x7) {
 | 
				
			||||||
 | 
							err ("error: bad message size");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//check pubkey availability
 | 
				
			||||||
 | 
						keyring::pubkey_entry*pke;
 | 
				
			||||||
 | 
						pke = KR.get_pubkey (msg.key_id);
 | 
				
			||||||
 | 
						if (!pke) {
 | 
				
			||||||
 | 
							err ("error: verification pubkey unavailable");
 | 
				
			||||||
 | 
							err ("info: requires key @" << msg.key_id);
 | 
				
			||||||
 | 
							if (!yes) {
 | 
				
			||||||
 | 
								err ("notice: not displaying unverified message");
 | 
				
			||||||
 | 
								err ("info: to see it, use yes option");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err ("warning: following message is UNVERIFIED");
 | 
				
			||||||
 | 
								msg.message.to_string (data);
 | 
				
			||||||
 | 
								out_bin (data);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 2; //missing key flag
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ( (!AS.count (msg.alg_id) )
 | 
				
			||||||
 | 
						     || (!AS[msg.alg_id]->provides_signatures() ) ) {
 | 
				
			||||||
 | 
							err ("error: verification algorithm unsupported");
 | 
				
			||||||
 | 
							err ("info: requires algorithm " << msg.alg_id
 | 
				
			||||||
 | 
							     << " with signature support");
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//do the verification
 | 
				
			||||||
 | 
						int r = msg.verify (AS, KR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err ("incoming signed message details:");
 | 
				
			||||||
 | 
						err ("  algorithm: " << msg.alg_id);
 | 
				
			||||||
 | 
						err ("  signed by: @" << msg.key_id);
 | 
				
			||||||
 | 
						err ("  signed local name: `" << pke->name << "'");
 | 
				
			||||||
 | 
						err ("  verification status: "
 | 
				
			||||||
 | 
						     << (r == 0 ?
 | 
				
			||||||
 | 
						         "GOOD signature ;-)" :
 | 
				
			||||||
 | 
						         "BAD signature :-(") );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r) {
 | 
				
			||||||
 | 
							if (!yes) {
 | 
				
			||||||
 | 
								err ("notice: not displaying unverified message");
 | 
				
			||||||
 | 
								err ("info: to see it, use yes option");
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								err ("warning: following message is UNVERIFIED");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (yes || !r) {
 | 
				
			||||||
 | 
							msg.message.to_string (data);
 | 
				
			||||||
 | 
							out_bin (data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (r) return 3; //verification failed flag
 | 
				
			||||||
 | 
						else return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,15 +37,15 @@ bool redirect_cout (const std::string& fn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define bufsize 1024
 | 
					#define bufsize 1024
 | 
				
			||||||
bool read_all_input (std::string&data)
 | 
					bool read_all_input (std::string&data, std::istream&input)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	data.clear();
 | 
						data.clear();
 | 
				
			||||||
	char buf[bufsize];
 | 
						char buf[bufsize];
 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		std::cin.read (buf, bufsize);
 | 
							input.read (buf, bufsize);
 | 
				
			||||||
		if (std::cin) data.append (buf, bufsize);
 | 
							if (input) data.append (buf, bufsize);
 | 
				
			||||||
		else if (std::cin.eof() ) {
 | 
							else if (input.eof() ) {
 | 
				
			||||||
			data.append (buf, std::cin.gcount() );
 | 
								data.append (buf, input.gcount() );
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		} else return false;
 | 
							} else return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,6 @@
 | 
				
			||||||
bool redirect_cin (const std::string& fn);
 | 
					bool redirect_cin (const std::string& fn);
 | 
				
			||||||
bool redirect_cout (const std::string& fn);
 | 
					bool redirect_cout (const std::string& fn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool read_all_input (std::string&);
 | 
					bool read_all_input (std::string&, std::istream&in = std::cin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue