ACC SHELL
/**
* File: modules/KeyManager.ycp
* Package: GPG Key Management
* Summary: Manages GPG keys in the package manager
* Authors: Ladislav Slezák <lslezak@novell.com>
*
* $Id: KeyManager.ycp 57028 2009-04-29 10:58:09Z lslezak $
*
*/
{
textdomain "packager";
module "KeyManager";
import "Report";
import "Directory";
import "String";
// the current state
list<map<string,any> > known_keys = [];
// keys to delete
list<map<string,any> > deleted_keys = [];
// keys to import from a file (file name => trusted flag)
list<map<string,any> > import_from_file = [];
boolean modified = false;
//////////////////////////////////////////////////////////////////////////////
/**
* Reset the internal state of the module. The current configuration and all
* changes are deleted.
*/
global void Reset()
{
known_keys = [];
deleted_keys = [];
import_from_file = [];
modified = false;
}
/**
* Read the current configuration from the package manager
* @return list the current configuration, nil when an error occurr
*/
list<map<string,any> > ReadCurrentKeys()
{
// read trusted keys
list<map<string,any> > ret = Pkg::GPGKeys(true);
y2milestone("Read configuration: %1", ret);
return ret;
}
/**
* Read the current configuration from the package manager. The previous changes are lost (@see Reset).
* The target system of the package manager must be initialized before reading GPG keys!
* @return boolean true on success
*/
global boolean Read()
{
if (size(known_keys) > 0)
{
y2warning("Rereading GPG keys from the package manager");
Reset();
}
known_keys = ReadCurrentKeys();
if (known_keys == nil)
{
known_keys = [];
return false;
}
return true;
}
/**
* Search a GPG key in the known keys
* @param key_id ID of the key
* @return map Data about the key or nil if the key was not found
*/
global map<string,any> SearchGPGKey(string key_id)
{
map<string,any> ret = nil;
// search the properties of the key
foreach(map<string,any> key, known_keys,
{
if (key["id"]:"" == key_id)
{
ret = key;
break;
}
}
);
return ret;
}
/**
* Apply the changes, update the current status
* @return boolean true on success
*/
global boolean Write()
{
if (!modified)
{
y2milestone("No change, nothing to write");
return true;
}
y2milestone("Writing key management configuration");
boolean ret = true;
// delete the keys marked for removal
foreach(map<string,any> deleted_key, deleted_keys,
{
y2milestone("Deleting key %1 ('%2')", deleted_key["id"]:"", deleted_key["name"]:"");
ret = Pkg::DeleteGPGKey(deleted_key["id"]:"", deleted_key["trusted"]:false) && ret;
}
);
// import the new keys
foreach(map<string,any> new_key, import_from_file,
{
y2milestone("Importing key %1 from '%2', trusted: %3", new_key["id"]:"", new_key["file"]:"", new_key["trusted"]:false);
ret = Pkg::ImportGPGKey(new_key["file"]:"", new_key["trusted"]:false) && ret;
}
);
// all changes are saved, reset them
deleted_keys = [];
import_from_file = [];
modified = false;
return ret;
}
/**
* Has been something changed?
* @return boolean true if something has been changed
*/
global boolean Modified()
{
return modified;
}
/**
* Return the current keys.
* @return list list of known GPG keys ($[ "id" : string, "name" : string, "trusted" : boolean ])
*/
global list<map<string,any> > GetKeys()
{
return known_keys;
}
/**
* Delete the key from the package manager
* @param key_id ID of the key to delete
* @return boolean true on success
*/
global boolean DeleteKey(string key_id)
{
if (key_id == nil || key_id == "")
{
y2error("Invalid key ID: %1", key_id);
return false;
}
// index of the key
integer found = nil;
integer i = 0;
// copy the key from known keys to the deleted list
foreach(map<string,any> key, known_keys,
{
if (key["id"]:"" == key_id)
{
deleted_keys = add(deleted_keys, key);
found = i;
}
i = i + 1;
}
);
// remove from known keys when found
if (found != nil)
{
known_keys = remove(known_keys, found);
}
boolean found_in_imported = false;
// remove from imported keys (deleting a key scheduled for import)
import_from_file = filter(map<string,any> new_key, import_from_file,
{
boolean found_key = (new_key["id"]:"" == key_id);
found_in_imported = found_in_imported || found_key;
return found_key;
}
);
modified = true;
return (found != nil);
}
/**
* Import key from a file
* @param file path to the file
* @param trusted true if the key is trusted
* @return map map with the key, nil when import fails (invalid key, not existing file, already imported key...)
*/
global map<string,any> ImportFromFile(string file, boolean trusted)
{
// check whether the file is valid, copy the file to the tmpdir
map<string,any> key = Pkg::CheckGPGKeyFile(file);
y2milestone("File content: %1", key);
if (key != nil && size(key) > 0)
{
// update the trusted flag
key["trusted"] = trusted;
}
else
{
Report::Error(sformat(_("File '%1'
doesn't contain a valid GPG key."), file));
return nil;
}
boolean known = false;
// check whether the key is already known
foreach(map<string,any> k, known_keys,
{
if (k["id"]:"" == key["id"]:"")
{
known = true;
}
}
);
if (known)
{
// %1 is key ID (e.g. A84EDAE89C800ACA), %2 is key name (e.g. "SuSE Package Signing Key <build@suse.de>")
Report::Error(sformat(_("Key '%1'
'%2'
is already known, it cannot be added again."), key["id"]:"", key["name"]:""));
return nil;
}
boolean found_in_deleted = false;
// check if the key is scheduled for removal
deleted_keys = filter(map<string,any> deleted_key, deleted_keys,
{
boolean key_found = (deleted_key["id"]:"" == key["id"]:"");
found_in_deleted = found_in_deleted || key_found;
return !key_found;
}
);
// the key was known, move it to the known list
if (found_in_deleted)
{
known_keys = add(known_keys, key);
return key;
}
// copy the key to the temporary directory (in fact the keys are imported in Write())
string tmpfile = sformat("%1/tmp_gpg_key.%2", Directory::tmpdir, size(known_keys));
string command = sformat("/bin/cp -- '%1' '%2'", String::Quote(file), String::Quote(tmpfile));
y2milestone("Copying the key: %1", command);
integer out = (integer)SCR::Execute(.target.bash, command);
if (out != 0)
{
Report::Error(_("Cannot copy the key to the temporary directory."));
return nil;
}
// store the import request
import_from_file = add(import_from_file, $[ "file" : tmpfile, "trusted" : trusted, "id" : key["id"]:"" ]);
// add the new key to the current config
known_keys = add(known_keys, key);
modified = true;
return key;
}
/* EOF */
}
ACC SHELL 2018