diff --git a/lib/signature.C b/lib/signature.C new file mode 100644 index 0000000000..6527313c68 --- /dev/null +++ b/lib/signature.C @@ -0,0 +1,225 @@ +// +// Copyright (C) 2006-2008 MTA SZTAKI +// +// Marosi Attila Csaba +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#include +#include "miofile.h" +#include "error_numbers.h" +#include "signatures.h" + +SIGNATURE::SIGNATURE() { + this->clear(); +} + +SIGNATURE::~SIGNATURE() { + // TODO +} + +void SIGNATURE::clear() { + this->type = MD5_HASH; // md5 hash by default + memset(this->subject, 0, sizeof(this->subject)); + memset(this->signature, 0, sizeof(this->signature)); +} + +SIGNATURES::SIGNATURES() { + // TODO +} + +SIGNATURES::~SIGNATURES() { + // TODO +} + +void SIGNATURES::clear() { + this->signatures.clear(); +} + +int SIGNATURES::count() { + return this->signatures.size(); +} + +int SIGNATURES::parse(XML_PARSER &xp) { + SIGNATURE sig; + int is_tag = false; + int in_entry = false; + int in_sig = false; + int parsed_one = false; + char tag[4096]; + char buf[256]; + + //printf("SIGNATURES::parse() starts.\n"); + //fflush(stdout); + + while (!xp.get(tag, sizeof(tag), (bool&)is_tag)) { + if (!strcmp(tag, "/signatures")) { + //printf("SIGNATURES::parse() ends.\n"); + //fflush(stdout); + return !in_entry && !in_sig && parsed_one; + } + if (in_sig) { + in_sig = false; + snprintf(sig.signature, sizeof(sig.signature), "%s", tag); + continue; + } + if (!is_tag) { + printf("(SIGNATURES): unexpected text: %s\n", tag); + continue; + } + if (in_entry) { + if (!strcmp(tag, "/entry")) { + in_entry = false; + in_sig = false; + if (strlen(sig.subject) == 0) { + printf("ERROR: subject is not set.\n"); + return false; + } + if (strlen(sig.signature) == 0) { + printf("ERROR: signature is not set.\n"); + return false; + } + this->signatures.push_back(sig); + parsed_one = true; + sig.clear(); + continue; + } + if (!strcmp(tag, "thesignature")) { + in_sig = true; + continue; + } + if (!strcmp(tag, "/thesignature")) { + in_sig = false; + continue; + } + if (xp.parse_str(tag, "subject", sig.subject, sizeof(sig.subject))) + continue; + else if (xp.parse_str(tag, "hash", sig.hash, sizeof(sig.hash))) + continue; + else if (xp.parse_str(tag, "type", buf, sizeof(buf))) { + if ((!strcmp(buf,"md5")) || (!strcmp(buf,"MD5"))) { + sig.type = MD5_HASH; + } else if ((!strcmp(buf,"sha1")) || (!strcmp(buf,"SHA1"))) { + sig.type = SHA1_HASH; + } + continue; + } + } else { + if (strstr(tag, "entry")) { + in_entry = true; + continue; + } + } + + } + return false; +} + +int SIGNATURES::parse_miofile_embed(MIOFILE &mf) { + XML_PARSER xp(&mf); + return this->parse(xp); +} + +int SIGNATURES::parse_file(const char* filename) { + FILE* f; + int retval; + + f = fopen(filename, "r"); + if (!f) + return ERR_FOPEN; + MIOFILE mf; + mf.init_file(f); + XML_PARSER xp(&mf); + if (!xp.parse_start("signatures")) { + return ERR_XML_PARSE; + } + retval = this->parse(xp); + fclose(f); + return retval; +} + +int SIGNATURES::parse_buffer(char* buf) { + MIOFILE mf; + int retval; + + mf.init_buf_read(buf); + XML_PARSER xp(&mf); + retval = this->parse(xp); + return retval; +} + +int SIGNATURES::parse_buffer_embed(char* buf) { + MIOFILE mf; + char tag[4096]; + int is_tag; + int s_found = false; + + mf.init_buf_read(buf); + XML_PARSER xp(&mf); + while (!xp.get(tag, sizeof(tag), (bool&)is_tag)) { + if (!strcmp(tag, "signatures")) { + s_found = true; + break; + } + } + if (s_found) + return this->parse(xp); + else + return false; +} + +void SIGNATURES::dump() { + MIOFILE m; + char buf[4096]; + + m.init_buf_write((char *)buf, 4096); + this->write(m, 4096); + printf("%s", buf); +} + +int SIGNATURES::write(MIOFILE &f, int max) { + f.printf("\n"); + for(int i=0;i < this->signatures.size(); i++) { + f.append(max, " \n"); + f.append(max, " \n%s\n", this->signatures.at(i).signature); + f.append(max, " \n"); + f.append(max, " %s\n", this->signatures.at(i).subject); + f.append(max, " %s\n", (this->signatures.at(i).type == MD5_HASH) ? "md5" : "sha1"); + f.append(max, " %s\n", this->signatures.at(i).hash); + f.append(max, " \n"); + } + f.append(max, "\n"); + return true; +} + +// atisu: MIOFILE::printf was modified to increase buffer pointer +int SIGNATURES::write(MIOFILE &f) { + if (this->signatures.size()==0) + return true; + f.printf("\n"); + for(int i=0;i < this->signatures.size(); i++) { + f.printf(" \n"); + f.printf(" \n%s\n", this->signatures.at(i).signature); + f.printf(" \n"); + f.printf(" %s\n", this->signatures.at(i).subject); + f.printf(" %s\n", (this->signatures.at(i).type == MD5_HASH) ? "md5" : "sha1"); + f.printf(" %s\n", this->signatures.at(i).hash); + f.printf(" \n"); + } + f.printf("\n"); + return true; +} + diff --git a/lib/signature.h b/lib/signature.h new file mode 100644 index 0000000000..6be7484819 --- /dev/null +++ b/lib/signature.h @@ -0,0 +1,82 @@ +// +// Copyright (C) 2006-2008 MTA SZTAKI +// +// Marosi Attila Csaba +// +// This is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; +// either version 2.1 of the License, or (at your option) any later version. +// +// This software is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// To view the GNU Lesser General Public License visit +// http://www.gnu.org/copyleft/lesser.html +// or write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef __SIGNATURES_H_ +#define __SIGNATURES_H_ + +#include +#include "parse.h" + +#ifndef MAX_SIGNATURE_LEN +#define MAX_SIGNATURE_LEN 4096 +#endif +#define MAX_SUBJECT_LEN 256 +#define MD5_HASH 0 +#define SHA1_HASH 1 + +struct SIGNATURE { +public: + char signature[MAX_SIGNATURE_LEN]; // RSA signature expected. + int type; // MD5_HASH or SHA1_HASH. Not used yet. + char subject[MAX_SUBJECT_LEN]; + char hash[9]; // 8 + '\0'... + SIGNATURE(); + ~SIGNATURE(); + void clear(); +}; + +class SIGNATURES { +public: + std::vector signatures; + SIGNATURES(); + ~SIGNATURES(); + // + // Parses an .xml signature file with the following structure: + // + // + // + // + //%signature% + // + // %certificate_subject% + // %md5_or_sha1(_with_rsa)% + // %certificate_hash% + // + // + // ... + // + // ... + // + int parse_file(const char* filename); + int parse_buffer(char* buf); + int write(MIOFILE &f); + int write(MIOFILE &f, int max); + // Parses from an already opened MIOFILE, the pointer should have + // passed the opening tag (no check is done for that). + int parse_miofile_embed(MIOFILE &mf); + int parse_buffer_embed(char* buf); + void dump(); + void clear(); + int count(); // return the total number of signatures. +private: + int parse(XML_PARSER &xp); +}; + +#endif //__SIGNATURES_H_