/* Add a particular public key to the archive. Copyright (C) 2004 Walter Landry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "../../config.h" #include "Spawn.hpp" #include "gvfs.hpp" #include "Temp_File.hpp" #include "get_gpg_name.hpp" #include "Parsed_Name.hpp" #include "tempdir.hpp" using namespace std; using namespace boost; namespace fs=boost::filesystem; using fs::path; void add_key_to_archive(const Parsed_Name &name, const string &key) { list gpg=get_gpg_name(); if(!gpg.empty()) { /* Get the old keyring */ gvfs::Init(); gvfs::uri public_keys(name.archive_location() / ",meta-info/public_keys"); Temp_File new_public_keys(tempdir(),",,public_keys"); /* This is an ugly hack to delete the autmatic backup file that gpg likes to make. */ Temp_File new_public_keys_backup(path(new_public_keys.path .string() + "~")); if(gvfs::exists(public_keys)) gvfs::copy(public_keys,new_public_keys.path.native_file_string()); /* Export the key into a file */ Temp_File new_key(tempdir(),",,new_key"); Spawn gpg_export; for(list::iterator i=gpg.begin(); i!=gpg.end(); ++i) gpg_export << *i; gpg_export << "--output" << new_key.path.native_file_string() << "--export" << key; int return_status; if(!gpg_export.execute(return_status,true) || return_status!=0) throw arx_error("Error when executing gpg to export the key " + key); /* Import the key into the keyring */ Spawn gpg_import; for(list::iterator i=gpg.begin(); i!=gpg.end(); ++i) gpg_import << *i; gpg_import << "--no-default-keyring" << "--keyring" << system_complete(new_public_keys.path).native_file_string() << "--import" << system_complete(new_key.path).native_file_string(); if(!gpg_import.execute(return_status,true) || return_status!=0) throw arx_error("Error when executing gpg to import the key\n\t" + key); /* Copy the result over, deleting any left-over new public keys */ gvfs::uri new_archive_keys(public_keys.string() + "_new"); if(gvfs::exists(new_archive_keys)) gvfs::remove(new_archive_keys); if(!exists(new_public_keys.path)) cerr << "INTERNAL ERROR: new public keys do not exist" << new_public_keys.path.string() << endl; /* We have to explicitly add the permissions for others to read the archive key list because gpg, by default, makes it impossible for that. */ struct stat path_stat; if(::stat((new_public_keys.path.native_file_string()).c_str(), &path_stat)) throw arx_error("Can't stat " + new_public_keys.path.native_file_string()); path_stat.st_mode|=(S_IRGRP | S_IROTH); ::chmod((new_public_keys.path.native_file_string()).c_str(), path_stat.st_mode); /* Finally, copy the archive keys over. */ gvfs::copy(gvfs::uri(new_public_keys.path.string()),new_archive_keys); gvfs::rename(new_archive_keys,public_keys); } else throw arx_error("ERROR: You can not add keys to archives, because ArX has not been compiled\nwith gpg support and you did not specify a gpg program with \"arx param\"."); }