[pacman-dev] [PATCH 4/4] pacman: implement signature check callback using an external command
Rémy Oudompheng
remyoudompheng at gmail.com
Sun Apr 10 07:40:20 EDT 2011
Signed-off-by: Rémy Oudompheng <remy at archlinux.org>
---
src/pacman/callback.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index 1ff9a47..06f161c 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -25,6 +25,7 @@
#include <string.h>
#include <sys/time.h>
#include <sys/types.h> /* off_t */
+#include <sys/wait.h> /* waitpid */
#include <unistd.h>
#include <wchar.h>
@@ -689,7 +690,79 @@ void cb_log(pmloglevel_t level, const char *fmt, va_list args)
/* Callback to check signatures with an external command */
int cb_checksig(const char *path, const pmpgpsig_t *sig) {
- return 0;
+ int ret = 0;
+ int retval;
+ int childpid;
+ char *parsedcmd;
+ int pipefd[2];
+
+ if(!config->checksigcommand) {
+ return -1;
+ }
+
+ parsedcmd = strdup(config->checksigcommand);
+ /* replace all occurrences of %f with the filename */
+ if(strstr(parsedcmd, "%f")) {
+ char *tempcmd = strreplace(parsedcmd, "%f", path);
+ free(parsedcmd);
+ parsedcmd = tempcmd;
+ }
+
+ /* execute the parsed command via /bin/sh -c */
+ pipe(pipefd);
+ childpid = fork();
+
+ if (childpid < 0) {
+ pm_printf(PM_LOG_ERROR, _("running ChecksigCommand: fork failed!\n"));
+ ret = -1;
+ goto cleanup;
+ } else if (childpid == 0) {
+ /* we are in the child */
+ close(pipefd[1]);
+ /* read from the pipe */
+ dup2(pipefd[0], 0);
+ pm_printf(PM_LOG_DEBUG, "child: running command: %s\n", parsedcmd);
+ if (execl("/bin/sh", "/bin/sh", "-c", parsedcmd, NULL) == -1)
+ exit(127);
+ } else {
+ /* we are still in pacman */
+ close(pipefd[0]);
+ size_t remaining;
+ const char *signature = alpm_pgpsig_get_raw(sig, &remaining);
+ if (! signature) {
+ close(pipefd[1]);
+ ret = -1;
+ goto wait;
+ }
+ while(remaining > 0) {
+ /* write signature into pipe */
+ ssize_t written = write(pipefd[1], signature, remaining);
+ if (written < 0) {
+ pm_printf(PM_LOG_ERROR, _("running ChecksigCommand: broken pipe!\n"));
+ ret = -1;
+ break;
+ }
+ signature += written;
+ remaining -= written;
+ }
+ close(pipefd[1]);
+ }
+
+wait:
+ waitpid(childpid, &retval, 0);
+
+ if(!WIFEXITED(retval)) {
+ /* exited abnormally */
+ pm_printf(PM_LOG_DEBUG, "ChecksigCommand exited abnormally "
+ "status (%d,%d)\n", retval >> 8, retval & 0xff);
+ ret = -1;
+ } else {
+ ret = (WEXITSTATUS(retval) == 0) ? 0 : 1;
+ }
+
+cleanup:
+ free(parsedcmd);
+ return ret;
}
/* vim: set ts=2 sw=2 noet: */
--
1.7.4.4
More information about the pacman-dev
mailing list