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) {
 | 
			
		||||
		err ("error: decryption privkey unavailable");
 | 
			
		||||
		err ("info: requires key @" << msg.key_id);
 | 
			
		||||
		return 1;
 | 
			
		||||
		return 2; //missing key flag
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//and the algorithm
 | 
			
		||||
| 
						 | 
				
			
			@ -404,7 +404,223 @@ int action_verify (bool armor, const std::string&detach,
 | 
			
		|||
                   bool clearsign, bool yes,
 | 
			
		||||
                   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
 | 
			
		||||
bool read_all_input (std::string&data)
 | 
			
		||||
bool read_all_input (std::string&data, std::istream&input)
 | 
			
		||||
{
 | 
			
		||||
	data.clear();
 | 
			
		||||
	char buf[bufsize];
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		std::cin.read (buf, bufsize);
 | 
			
		||||
		if (std::cin) data.append (buf, bufsize);
 | 
			
		||||
		else if (std::cin.eof() ) {
 | 
			
		||||
			data.append (buf, std::cin.gcount() );
 | 
			
		||||
		input.read (buf, bufsize);
 | 
			
		||||
		if (input) data.append (buf, bufsize);
 | 
			
		||||
		else if (input.eof() ) {
 | 
			
		||||
			data.append (buf, input.gcount() );
 | 
			
		||||
			return true;
 | 
			
		||||
		} else return false;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,6 +41,6 @@
 | 
			
		|||
bool redirect_cin (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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue