/* Chrysalide - Outil d'analyse de fichiers binaires * secstorage.c - équivalent Python du fichier "core/secstorage.c" * * Copyright (C) 2025 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide 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 3 of the License, or * (at your option) any later version. * * Chrysalide 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 "secstorage.h" #include #include "../access.h" #include "../convert.h" #include "../helpers.h" /* Détermine si une clef de chiffrement protégée est en place. */ static PyObject *py_secstorage_has_secret_storage_key(PyObject *, PyObject *); /* Définit un mot de passe pour protéger une clef maître. */ static PyObject *py_secstorage_set_secret_storage_password(PyObject *, PyObject *); /* Détermine si la clef de chiffrement maître est vérouillée. */ static PyObject *py_secstorage_is_secret_storage_locked(PyObject *, PyObject *); /* Déverrouille la clef de chiffrement maître. */ static PyObject *py_secstorage_unlock_secret_storage(PyObject *, PyObject *); /* Verrouille la clef de chiffrement maître. */ static PyObject *py_secstorage_lock_secret_storage(PyObject *, PyObject *); /* Chiffre des données avec la clef de chiffrement maître. */ static PyObject *py_secstorage_encrypt_secret_storage_data(PyObject *, PyObject *); /* Déchiffre des données avec la clef de chiffrement maître. */ static PyObject *py_secstorage_decrypt_secret_storage_data(PyObject *, PyObject *); /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Détermine si un mot de passe est actuellement en place. * * * * Retour : Bilan de l'analyse. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_has_secret_storage_key(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ bool status; /* Bilan de situation */ #define SECSTORAGE_HAS_SECRET_STORAGE_KEY_METHOD PYTHON_METHOD_DEF \ ( \ has_secret_storage_key, "/, settings=None", \ METH_VARARGS, py_secstorage, \ "Indicate if a master key used for protecting secrets seems to have"\ " been defined.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default.\n" \ "\n" \ "The result is a boolean status: *True* if the master key seems" \ " to exist, *False* otherwise." \ ) ret = PyArg_ParseTuple(args, "O&", convert_to_gsettings, &settings); if (!ret) return NULL; status = has_secret_storage_key(settings); result = status ? Py_True : Py_False; Py_INCREF(result); return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Définit un mot de passe pour protéger une clef maître. * * * * Retour : Bilan de la mise en place. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_set_secret_storage_password(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ const char *passwd; /* Mot de passe associé */ int ret; /* Bilan de lecture des args. */ bool status; /* Bilan de situation */ #define SECSTORAGE_SET_SECRET_STORAGE_PASSWORD_METHOD PYTHON_METHOD_DEF \ ( \ set_secret_storage_password, "/, settings=None, password=''", \ METH_VARARGS, py_secstorage, \ "Create a master key used for protecting secrets. This key is" \ " itself protected by the provided password.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default. The supplied" \ " *password* has to be a string.\n" \ "\n" \ "The result is a boolean status: *True* if the operation successed,"\ " *False* otherwise." \ ) settings = NULL; passwd = ""; ret = PyArg_ParseTuple(args, "|O&s", convert_to_gsettings, &settings, &passwd); if (!ret) return NULL; status = set_secret_storage_password(settings, passwd); result = status ? Py_True : Py_False; Py_INCREF(result); return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Détermine si la clef de chiffrement maître est vérouillée. * * * * Retour : Bilan de la détermination. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_is_secret_storage_locked(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ bool status; /* Bilan de situation */ #define SECSTORAGE_IS_SECRET_STORAGE_LOCKED_METHOD PYTHON_METHOD_DEF \ ( \ is_secret_storage_locked, "/, settings=None", \ METH_VARARGS, py_secstorage, \ "Indicate if the master key used for protecting secrets is" \ " currently decrypted in memory.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default.\n" \ "\n" \ "The result is a boolean status: *True* if the master key is" \ " unlocked and ready for use, *False* otherwise." \ ) settings = NULL; ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); if (!ret) return NULL; status = is_secret_storage_locked(settings); result = status ? Py_True : Py_False; Py_INCREF(result); return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Déverrouille la clef de chiffrement maître. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_unlock_secret_storage(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ const char *passwd; /* Mot de passe associé */ int ret; /* Bilan de lecture des args. */ bool status; /* Bilan de situation */ #define SECSTORAGE_UNLOCK_SECRET_STORAGE_METHOD PYTHON_METHOD_DEF \ ( \ unlock_secret_storage, "/, settings=None, password=''", \ METH_VARARGS, py_secstorage, \ "Decrypt in memory the master key used for protecting secrets.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default. The supplied" \ " *password* is the primary password used to protect this key.\n" \ "\n" \ "The result is a boolean status: *True* if the operation successed" \ " or if the master key is already unlocked, *False* otherwise." \ ) settings = NULL; passwd = ""; ret = PyArg_ParseTuple(args, "|O&s", convert_to_gsettings, &settings, &passwd); if (!ret) return NULL; status = unlock_secret_storage(settings, passwd); result = status ? Py_True : Py_False; Py_INCREF(result); return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Verrouille la clef de chiffrement maître. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_lock_secret_storage(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ #define SECSTORAGE_LOCK_SECRET_STORAGE_METHOD PYTHON_METHOD_DEF \ ( \ lock_secret_storage, "/, settings=None", \ METH_VARARGS, py_secstorage, \ "Clear from memory the master key used for protecting secrets.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default." \ ) settings = NULL; ret = PyArg_ParseTuple(args, "|O&", convert_to_gsettings, &settings); if (!ret) return NULL; lock_secret_storage(settings); result = Py_None; Py_INCREF(result); return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Chiffre des données avec la clef de chiffrement maître. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_encrypt_secret_storage_data(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ const char *data_in; /* Données d'entrée à chiffrer */ Py_ssize_t size_in; /* Quantité de ces données */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ sized_binary_t in; /* Données à chiffer */ bool status; /* Bilan de situation */ sized_binary_t out; /* Données chiffrées */ #define SECSTORAGE_ENCRYPT_SECRET_STORAGE_DATA_METHOD PYTHON_METHOD_DEF \ ( \ encrypt_secret_storage_data, "data, /, settings=None", \ METH_VARARGS, py_secstorage, \ "Encrypt data using an unlocked the master key.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default." \ "\n" \ "The result is either encrypted data as bytes in case of success," \ " or *None* in case of failure." \ ) settings = NULL; ret = PyArg_ParseTuple(args, "s#|O&", &data_in, &size_in, convert_to_gsettings, &settings); if (!ret) return NULL; in.static_data = data_in; in.size = size_in; status = encrypt_secret_storage_data(settings, &in, &out); if (status) { result = PyBytes_FromStringAndSize(out.static_data, out.size); exit_sized_binary(&out); } else { result = Py_None; Py_INCREF(result); } return result; } /****************************************************************************** * * * Paramètres : self = objet Python concerné par l'appel. * * args = arguments fournis à l'appel. * * * * Description : Déchiffre des données avec la clef de chiffrement maître. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ static PyObject *py_secstorage_decrypt_secret_storage_data(PyObject *self, PyObject *args) { PyObject *result; /* Conversion à retourner */ const char *data_in; /* Données d'entrée à chiffrer */ Py_ssize_t size_in; /* Quantité de ces données */ GSettings *settings; /* Configuration à considérer */ int ret; /* Bilan de lecture des args. */ sized_binary_t in; /* Données à chiffer */ bool status; /* Bilan de situation */ sized_binary_t out; /* Données chiffrées */ #define SECSTORAGE_DECRYPT_SECRET_STORAGE_DATA_METHOD PYTHON_METHOD_DEF \ ( \ decrypt_secret_storage_data, "data, /, settings=None", \ METH_VARARGS, py_secstorage, \ "Decrypt data using an unlocked the master key.\n" \ "\n" \ "The *settings* arguement must point to a GSettings intance; the" \ " main configuration settings are used by default." \ "\n" \ "The result is either decrypted data as bytes in case of success," \ " or *None* in case of failure." \ ) settings = NULL; ret = PyArg_ParseTuple(args, "s#|O&", &data_in, &size_in, convert_to_gsettings, &settings); if (!ret) return NULL; in.static_data = data_in; in.size = size_in; status = decrypt_secret_storage_data(settings, &in, &out); if (status) { result = PyBytes_FromStringAndSize(out.static_data, out.size); exit_sized_binary(&out); } else { result = Py_None; Py_INCREF(result); } return result; } /****************************************************************************** * * * Paramètres : - * * * * Description : Définit une extension du module 'core' à compléter. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool populate_core_module_with_secstorage(void) { bool result; /* Bilan à retourner */ PyObject *module; /* Module à recompléter */ static PyMethodDef py_secstorage_methods[] = { SECSTORAGE_HAS_SECRET_STORAGE_KEY_METHOD, SECSTORAGE_SET_SECRET_STORAGE_PASSWORD_METHOD, SECSTORAGE_IS_SECRET_STORAGE_LOCKED_METHOD, SECSTORAGE_UNLOCK_SECRET_STORAGE_METHOD, SECSTORAGE_LOCK_SECRET_STORAGE_METHOD, SECSTORAGE_ENCRYPT_SECRET_STORAGE_DATA_METHOD, SECSTORAGE_DECRYPT_SECRET_STORAGE_DATA_METHOD, { NULL } }; module = get_access_to_python_module("pychrysalide.core"); result = register_python_module_methods(module, py_secstorage_methods); return result; }