diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 805855b..ec050f3 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -29,14 +29,15 @@ decryptd_la_SOURCES = \ decryptd/main.c askpassd_la_SOURCES = \ + askpassd/question.c \ + askpassd/question.h \ askpassd/askp.c \ askpassd/askp.h \ askpassd/iface.c \ askpassd/iface.h \ askpassd/list.c \ askpassd/list.h \ - askpassd/main.c \ - askpassd/main.h + askpassd/main.c install-data-hook: $(MKDIR_P) $(DESTDIR)/$(DEO_CONF)/decrypt.d diff --git a/src/plugins/askpassd/askp.c b/src/plugins/askpassd/askp.c index 7abe7b1..286a4de 100644 --- a/src/plugins/askpassd/askp.c +++ b/src/plugins/askpassd/askp.c @@ -17,32 +17,18 @@ */ #define _GNU_SOURCE -#include "../../cleanup.h" #include "askp.h" -#include "list.h" -#include "main.h" +#include "question.h" +#include "../../cleanup.h" +#include "../../misc.h" #include -#include #include -#include -#include -#include -#include #include #include -#include -#include -#include -#include #include -#define UUID_DIR "/dev/disk/by-uuid" #define ASK_DIR "/run/systemd/ask-password" -#define SECTION "[Ask]\n" -#define PREFIX_ID "\nId=cryptsetup:" -#define PREFIX_SOCKET "\nSocket=" -#define PREFIX_NOTAFTER "\nNotAfter=" struct askp { struct list list; @@ -51,165 +37,6 @@ struct askp { int wfd; }; -struct item { - struct list list; - char *name; - char *uuid; - char *sock; - struct timespec time; -}; - -static char * -find_uuid_for_dev(const char *dev) -{ - char dpath[PATH_MAX]; - AUTO(DIR, dir); - - if (realpath(dev, dpath) == NULL) - return NULL; - - dir = opendir(UUID_DIR); - if (dir == NULL) - return NULL; - - for (struct dirent *de = readdir(dir); de; de = readdir(dir)) { - char rpath[PATH_MAX]; - char path[PATH_MAX]; - - if (de->d_type != DT_LNK) - continue; - - if (snprintf(path, sizeof(path), "%s/%s", UUID_DIR, de->d_name) < 0) - continue; - - if (!realpath(path, rpath)) - continue; - - if (strcmp(rpath, dpath) != 0) - continue; - - return strdup(de->d_name); - } - - return NULL; -} - -static void -item_free(struct item *a) -{ - if (a == NULL) - return; - - free(a->uuid); - free(a->sock); - free(a->name); - free(a); -} - -static char * -find_prefix_in_section(const char *start, const char *end, const char *prefix) -{ - char *startl = NULL; - char *endl = NULL; - size_t plen; - - if (start == NULL || end == NULL || prefix == NULL) - return NULL; - - plen = strlen(prefix); - - startl = memmem(start, end - start, prefix, plen); - if (startl == NULL) - return NULL; - startl += plen; - - endl = memchr(startl, '\n', end - startl); - if (endl == NULL) - return NULL; - - return strndup(startl, endl - startl); -} - -static struct item * -item_new(const char *name) -{ - struct item *item = NULL; - struct stat st = {}; - char path[PATH_MAX]; - char *start = NULL; - char *file = NULL; - char *end = NULL; - char *dev = NULL; - char *na = NULL; - AUTO_FD(fd); - - if (snprintf(path, sizeof(path), "%s/%s", ASK_DIR, name) < 0) - return NULL; - - fd = open(path, O_RDONLY); - if (fd < 0) - return NULL; - - if (fstat(fd, &st) != 0) - goto error; - - file = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (!file) - goto error; - - start = memmem(file, st.st_size, SECTION, strlen(SECTION)); - if (!start) - goto error; - - end = memmem(start, st.st_size - (start - file), "\n[", 2); - if (!end) - end = file + st.st_size; - - item = calloc(1, sizeof(struct item)); - if (!item) - goto error; - - item->name = strdup(name); - if (!item->name) - goto error; - - dev = find_prefix_in_section(start, end, PREFIX_ID); - if (!dev) - goto error; - - item->uuid = find_uuid_for_dev(dev); - free(dev); - if (!item->uuid) - goto error; - - na = find_prefix_in_section(start, end, PREFIX_NOTAFTER); - if (na) { - long long usec; - - errno = 0; - usec = strtoll(na, NULL, 10); - if (errno != 0) - goto error; - - item->time.tv_sec = usec / 1000000; - item->time.tv_nsec = usec % 1000000 * 1000; - } - - item->sock = find_prefix_in_section(start, end, PREFIX_SOCKET); - if (!item->sock) - goto error; - - munmap(file, st.st_size); - return item; - -error: - if (file) - munmap(file, st.st_size); - - item_free(item); - return NULL; -} - static struct inotify_event * for_event(struct inotify_event *e, uint8_t *buf, size_t len) #define for_event(n, b, l) \ @@ -257,17 +84,17 @@ askp_new(struct askp **ctx, struct pollfd *fd) goto error; for (struct dirent *de = readdir(dir); de; de = readdir(dir)) { - struct item *item; + struct question *q; if (strncmp("ask.", de->d_name, 4) != 0) continue; - item = item_new(de->d_name); - if (item != NULL) - list_add_after(&(*ctx)->list, &item->list); + q = question_new(ASK_DIR, de->d_name); + if (q != NULL) + list_add_after(&(*ctx)->list, &q->list); } - fd->events = POLLIN | POLLPRI | POLLRDHUP; + fd->events = POLLIN | POLLPRI; fd->fd = (*ctx)->ifd; return 0; @@ -277,16 +104,21 @@ askp_new(struct askp **ctx, struct pollfd *fd) return ret; } -int -askp_event(struct askp *ctx) +bool +askp_question(struct askp *ctx, struct pollfd *fd) { uint8_t buf[8192] align_as(struct inotify_event); - struct item *item; + struct question *q = NULL; + bool havenew = false; ssize_t len; - while ((len = read(ctx->ifd, buf, sizeof(buf))) < 0) { + if ((fd->revents & fd->events) == 0) + return false; + fd->revents = 0; + + while ((len = read(fd->fd, buf, sizeof(buf))) < 0) { if (errno != EAGAIN) - return errno; + return false; } for_event(e, buf, len) { @@ -294,72 +126,108 @@ askp_event(struct askp *ctx) continue; if (e->mask & IN_MOVED_TO) { - item = item_new(e->name); - if (item != NULL) - list_add_after(&ctx->list, &item->list); + q = question_new(ASK_DIR, e->name); + if (q != NULL) { + list_add_after(&ctx->list, &q->list); + havenew = true; + } continue; } - LIST_FOREACH(&ctx->list, struct item, item, list) { - if (strcmp(item->name, e->name) == 0) { - list_pop(&item->list); - item_free(item); + LIST_FOREACH(&ctx->list, struct question, q, list) { + if (strcmp(q->name, e->name) == 0) { + list_pop(&q->list); + free(q); break; } } } - return 0; + return havenew; } void -askp_process(struct askp *ctx, struct list *keys) +askp_process(struct askp *ctx, char *argv[], const char *keysdir) { + char hex[4096] = { '+' }; struct timespec now; if (clock_gettime(CLOCK_MONOTONIC, &now) != 0) return; - LIST_FOREACH(&ctx->list, struct item, item, list) { - struct sockaddr_un addr = { AF_UNIX }; - struct key *key = NULL; + LIST_FOREACH(&ctx->list, struct question, q, list) { + char path[strlen(keysdir) + strlen(q->uuid) + 2]; + AUTO_FD(rfile); + AUTO_FD(rpipe); + + strcpy(path, keysdir); + strcat(path, "/"); + strcat(path, q->uuid); - if (item->time.tv_sec != 0 || item->time.tv_nsec != 0) { - if (item->time.tv_sec < now.tv_sec) + if (q->time.tv_sec != 0 || q->time.tv_nsec != 0) { + if (q->time.tv_sec < now.tv_sec) continue; - if (item->time.tv_sec == now.tv_sec && - item->time.tv_nsec < now.tv_nsec) + if (q->time.tv_sec == now.tv_sec && + q->time.tv_nsec < now.tv_nsec) continue; } - LIST_FOREACH(keys, struct key, k, list) { - if (strcmp(k->uuid, item->uuid) == 0) { - key = k; - break; - } - } - if (!key) + rfile = open(path, O_RDONLY); + if (rfile < 0) { + fprintf(stderr, "Unable to open keyfile (%s): %s\n", + path, strerror(errno)); continue; + } else { + AUTO_FD(wpipe); + int err; - char buf[key->len + 2]; + err = deo_pipe(&rpipe, &wpipe); + if (err != 0) { + fprintf(stderr, "Error making pipe: %s\n", strerror(err)); + continue; + } - buf[0] = '+'; - strncpy(buf + 1, (char *) key->key, key->len); + /* NOTE: this code depends on the kernel's pipe buffer being + * larger than size. This should always be the case with these + * short keys. */ + err = deo_run(argv, rfile, wpipe); + if (err != 0) { + fprintf(stderr, "%s decryption error: %s\n", + q->uuid, strerror(err)); + continue; + } else { + fprintf(stderr, "%s decryption success\n", q->uuid); + } + } + + for (ssize_t r; (r = read(rpipe, hex + strlen(hex), + sizeof(hex) - strlen(hex) - 1)) != 0; ) { + if (r < 0) { + fprintf(stderr, "%s read error: %s\n", + q->uuid, strerror(errno)); + break; + } + } - strcpy(addr.sun_path, item->sock); - sendto(ctx->sock, buf, sizeof(buf), 0, &addr, sizeof(addr)); + sendto(ctx->sock, hex, strlen(hex), 0, &q->sock, sizeof(q->sock)); } } +bool +askp_more(struct askp *ctx) +{ + return !LIST_EMPTY(&ctx->list); +} + void askp_free(struct askp *ctx) { if (!ctx) return; - LIST_FOREACH(&ctx->list, struct item, item, list) - item_free(item); + LIST_FOREACH(&ctx->list, struct question, q, list) + free(q); if (ctx->sock > 0) close(ctx->sock); diff --git a/src/plugins/askpassd/askp.h b/src/plugins/askpassd/askp.h index 637676d..0740ba4 100644 --- a/src/plugins/askpassd/askp.h +++ b/src/plugins/askpassd/askp.h @@ -19,6 +19,8 @@ #pragma once #include +#include + #include "list.h" struct askp; @@ -26,11 +28,14 @@ struct askp; int askp_new(struct askp **ctx, struct pollfd *fd); -int -askp_event(struct askp *ctx); +bool +askp_question(struct askp *ctx, struct pollfd *fd); void -askp_process(struct askp *ctx, struct list *keys); +askp_process(struct askp *ctx, char *argv[], const char *keysdir); + +bool +askp_more(struct askp *ctx); void askp_free(struct askp *ctx); diff --git a/src/plugins/askpassd/iface.c b/src/plugins/askpassd/iface.c index 0232270..e6f1a74 100644 --- a/src/plugins/askpassd/iface.c +++ b/src/plugins/askpassd/iface.c @@ -18,21 +18,10 @@ #define _GNU_SOURCE #include "iface.h" -#include "main.h" #include "../../cleanup.h" #include "../../misc.h" -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include @@ -40,10 +29,6 @@ #include #include -struct iface { - int fd; -}; - static int request_existing(int sock, int family) { @@ -60,83 +45,40 @@ request_existing(int sock, int family) } int -iface_new(struct iface **ctx, struct pollfd *fd) +iface_new(struct pollfd *fd) { struct sockaddr_nl addr = { .nl_family = AF_NETLINK, .nl_groups = RTMGRP_IPV4_ROUTE | RTMGRP_IPV6_ROUTE }; - int ret; - - *ctx = calloc(1, sizeof(struct iface)); - if (!*ctx) - return ENOMEM; - (*ctx)->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if ((*ctx)->fd < 0) - goto error; + fd->events = POLLIN | POLLPRI; + fd->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (fd->fd < 0) + return errno; - if (bind((*ctx)->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) - goto error; + if (bind(fd->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) + return errno; - request_existing((*ctx)->fd, AF_INET); - request_existing((*ctx)->fd, AF_INET6); + request_existing(fd->fd, AF_INET); + request_existing(fd->fd, AF_INET6); - fd->events = POLLIN | POLLPRI | POLLRDHUP; - fd->fd = (*ctx)->fd; return 0; - -error: - ret = errno; - iface_free(*ctx); - return ret; } -static ssize_t -decrypt(char *argv[], const char *keyfile, ssize_t size, uint8_t *key) -{ - AUTO_FD(rfile); - AUTO_FD(rpipe); - ssize_t t = 0; - int err; - - rfile = open(keyfile, O_RDONLY); - if (rfile < 0) - return -errno; - else { - AUTO_FD(wpipe); - - if (deo_pipe(&rpipe, &wpipe) != 0) - return -errno; - - /* NOTE: this code depends on the kernel's pipe buffer being larger - * than size. This should always be the case with these short keys. */ - err = deo_run(argv, rfile, wpipe); - if (err != 0) - return -err; - } - - for (ssize_t r; (r = read(rpipe, key + t, size - t)) != 0; t += r) { - if (r < 0) - return -errno; - } - - return t; -} - - -int -iface_event(struct iface *ctx, char *argv[], - const char *keysdir, struct list *keys) +bool +iface_route(struct pollfd *fd) { uint8_t buf[4096] align_as(struct nlmsghdr); - bool havenew = false; - AUTO(DIR, dir); int len; - while ((len = read(ctx->fd, buf, sizeof(buf))) < 0) { + if ((fd->revents & fd->events) == 0) + return false; + fd->revents = 0; + + while ((len = read(fd->fd, buf, sizeof(buf))) < 0) { if (errno != EAGAIN) - return errno; + return false; } for (struct nlmsghdr *msghdr = (struct nlmsghdr *) buf; @@ -149,71 +91,10 @@ iface_event(struct iface *ctx, char *argv[], switch (rtmsg->rtm_type) { case RTN_LOCAL: case RTN_UNICAST: - havenew = true; - break; + return true; } - break; } } - if (!havenew) - return 0; - - dir = opendir(keysdir); - if (dir == NULL) - return errno; - - for (struct dirent *de = readdir(dir); de; de = readdir(dir)) { - struct key *key = NULL; - bool already = false; - char path[PATH_MAX]; - - if (!deo_isreg(keysdir, de)) - continue; - - LIST_FOREACH(keys, struct key, k, list) { - if (strcmp(k->uuid, de->d_name) == 0) { - already = true; - break; - } - } - if (already) - continue; - - len = snprintf(path, sizeof(path), "%s/%s", keysdir, de->d_name); - if (len < 0 || len == sizeof(path)) - continue; - - key = calloc(1, sizeof(struct key)); - if (key == NULL) - continue; - - key->len = decrypt(argv, path, sizeof(key->key), key->key); - if (key->len < 0) { - fprintf(stderr, "Unable to decrypt key (%s): %s\n", - de->d_name, strerror(-key->len)); - free(key); - continue; - } - - fprintf(stderr, "Received key for %s\n", de->d_name); - fsync(STDERR_FILENO); - - strncpy(key->uuid, de->d_name, sizeof(key->uuid)); - list_add_after(keys, &key->list); - } - - return 0; -} - -void -iface_free(struct iface *ctx) -{ - if (!ctx) - return; - - if (ctx->fd > 0) - close(ctx->fd); - - free(ctx); + return false; } diff --git a/src/plugins/askpassd/iface.h b/src/plugins/askpassd/iface.h index 117ece8..1d950b8 100644 --- a/src/plugins/askpassd/iface.h +++ b/src/plugins/askpassd/iface.h @@ -19,16 +19,14 @@ #pragma once #include +#include #include "list.h" -struct iface; - int -iface_new(struct iface **ctx, struct pollfd *fd); +iface_new(struct pollfd *fd); -int -iface_event(struct iface *ctx, char *argv[], - const char *keysdir, struct list *keys); +bool +iface_route(struct pollfd *fd); void -iface_free(struct iface *ctx); +iface_decrypt(char *argv[], const char *keysdir, struct list *keys); diff --git a/src/plugins/askpassd/list.h b/src/plugins/askpassd/list.h index ba40a6a..30d068f 100644 --- a/src/plugins/askpassd/list.h +++ b/src/plugins/askpassd/list.h @@ -32,6 +32,8 @@ struct list { (type *) ((void *) (item) - offsetof(type, member)); \ }) +#define LIST_EMPTY(list) ((list)->prev == (list) && (list)->next == (list)) + #define LIST_FOREACH(list, type, name, member) \ for (type *__lst = LIST_ITEM(list, type, member), \ *name = LIST_ITEM(__lst->member.next, type, member), \ diff --git a/src/plugins/askpassd/main.c b/src/plugins/askpassd/main.c index de4664e..329ea05 100644 --- a/src/plugins/askpassd/main.c +++ b/src/plugins/askpassd/main.c @@ -21,8 +21,6 @@ #include "../main.h" #include "askp.h" #include "iface.h" -#include "list.h" -#include "main.h" #include #include @@ -32,6 +30,10 @@ #include #include +#define TIMEOUT_BASE 5000 +#define TIMEOUT_EXT (rand() % 295000) +#define ALLCNT (sizeof(struct all) / sizeof(struct pollfd)) + static void on_signal(int sig) { @@ -44,19 +46,29 @@ option(char c, const char *arg, const char **misc) return true; } +struct all { + struct pollfd askp; + struct pollfd iface; +}; + static int askpass(int argc, char *argv[]) { const char *keydir = DEO_CONF "/disks.d"; - struct iface *iface = NULL; + int timeout = TIMEOUT_BASE; AUTO_STACK(X509, anchors); struct askp *askp = NULL; int ret = EXIT_FAILURE; char *dargs[argc + 1]; - struct pollfd fds[2]; struct stat st; + int events; LIST(keys); + union { + struct pollfd all[ALLCNT]; + struct all ind; + } fds; + if (!deo_getopt(argc, argv, "hk:", "a:", NULL, NULL, option, &keydir, deo_anchors, &anchors)) { fprintf(stderr, @@ -76,10 +88,10 @@ askpass(int argc, char *argv[]) || !S_ISDIR(st.st_mode)) error(EXIT_FAILURE, errno, "Unable to access key directory"); - if (iface_new(&iface, &fds[0]) != 0) + if (askp_new(&askp, &fds.ind.askp) != 0) goto error; - if (askp_new(&askp, &fds[1]) != 0) + if (iface_new(&fds.ind.iface) != 0) goto error; signal(SIGINT, on_signal); @@ -88,35 +100,41 @@ askpass(int argc, char *argv[]) signal(SIGUSR1, on_signal); signal(SIGUSR2, on_signal); - while (poll(fds, sizeof(fds) / sizeof(*fds), 30000) > 0) { - for (size_t i = 0; i < sizeof(fds) / sizeof(*fds); i++) { - if (fds[i].revents & (POLLRDHUP | POLLERR | POLLHUP | POLLNVAL)) - goto error; - } + for (int i = 0; i < ALLCNT; i++) + fds.all[i].events |= POLLRDHUP; - if (fds[0].revents & fds[0].events) { - if (iface_event(iface, dargs, keydir, &keys) != 0) + while ((events = poll(fds.all, ALLCNT, timeout)) >= 0) { + bool process = false; + + for (int i = 0; i < ALLCNT; i++) { + short mask = ~fds.all[i].events | POLLRDHUP; + if (fds.all[i].revents & mask) goto error; } - fds[0].revents = 0; - if (fds[1].revents & fds[1].events) { - if (askp_event(askp) != 0) - goto error; + if (events == 0) { + askp_process(askp, dargs, keydir); + + if (!askp_more(askp)) + break; + + timeout = TIMEOUT_BASE + TIMEOUT_EXT; + continue; } - fds[1].revents = 0; - askp_process(askp, &keys); + timeout = TIMEOUT_BASE; + process |= iface_route(&fds.ind.iface); + process |= askp_question(askp, &fds.ind.askp); + if (process) + askp_process(askp, dargs, keydir); } if (errno == EINTR || errno == 0) ret = EXIT_SUCCESS; error: - LIST_FOREACH(&keys, struct key, key, list) - free(key); - - iface_free(iface); + close(fds.ind.iface.fd); + close(fds.ind.askp.fd); askp_free(askp); return ret; } diff --git a/src/plugins/askpassd/question.c b/src/plugins/askpassd/question.c new file mode 100644 index 0000000..3168340 --- /dev/null +++ b/src/plugins/askpassd/question.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015 Red Hat, Inc. + * Author: Nathaniel McCallum + * + * 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 3 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, see . + */ + +#define _GNU_SOURCE +#include "question.h" +#include "../../cleanup.h" + +#include +#include +#include +#include +#include + +#define UUID_DIR "/dev/disk/by-uuid" +#define SECTION "[Ask]\n" +#define PREFIX_ID "\nId=cryptsetup:" +#define PREFIX_SOCKET "\nSocket=" +#define PREFIX_NOTAFTER "\nNotAfter=" + +static int +find_prefix_in_section(const char *start, const char *end, const char *prefix, + char *out, size_t outlen) +{ + char *startl = NULL; + char *endl = NULL; + ssize_t plen; + + if (start == NULL || end == NULL || prefix == NULL) + return EINVAL; + + plen = strlen(prefix); + + startl = memmem(start, end - start, prefix, plen); + if (startl == NULL) + return NULL; + startl += plen; + + endl = memchr(startl, '\n', end - startl); + if (endl == NULL) + return ENOENT; + + if (outlen < endl - startl + 1) + return E2BIG; + + plen = snprintf(out, endl - startl + 1, "%s", startl); + if (plen < 0) + return errno; + + return 0; +} + +static int +find_uuid_for_dev(const char *dev, char *out, size_t outlen) +{ + char dpath[PATH_MAX]; + AUTO(DIR, dir); + + if (realpath(dev, dpath) == NULL) + return errno; + + dir = opendir(UUID_DIR); + if (dir == NULL) + return errno; + + for (struct dirent *de = readdir(dir); de; de = readdir(dir)) { + char path[strlen(UUID_DIR) + strlen(de->d_name) + 2]; + char rpath[PATH_MAX]; + + if (de->d_type != DT_LNK) + continue; + + strcpy(path, UUID_DIR); + strcat(path, "/"); + strcat(path, de->d_name); + + if (!realpath(path, rpath)) + continue; + + if (strcmp(rpath, dpath) != 0) + continue; + + if (snprintf(out, outlen, "%s", de->d_name) != strlen(de->d_name)) + return ENAMETOOLONG; + + return 0; + } + + return ENOENT; +} + +struct question * +question_new(const char *dir, const char *name) +{ + struct question *q = NULL; + struct stat st = {}; + char tmp[PATH_MAX]; + char *start = NULL; + char *file = NULL; + char *end = NULL; + AUTO_FD(fd); + int err; + + q = calloc(1, sizeof(struct question)); + if (!q) + goto error; + q->sock.sun_family = AF_UNIX; + + if (snprintf(q->name, sizeof(q->name), "%s", name) < 0) + goto error; + + err = snprintf(tmp, sizeof(tmp), "%s/%s", dir, name); + if (err < 0) + goto error; + + fd = open(tmp, O_RDONLY); + if (fd < 0) + goto error; + + if (fstat(fd, &st) != 0) + goto error; + + file = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (!file) + goto error; + + start = memmem(file, st.st_size, SECTION, strlen(SECTION)); + if (!start) + goto error; + + end = memmem(start, st.st_size - (start - file), "\n[", 2); + if (!end) + end = file + st.st_size; + + err = find_prefix_in_section(start, end, PREFIX_ID, tmp, sizeof(tmp)); + if (err != 0) + goto error; + + err = find_uuid_for_dev(tmp, q->uuid, sizeof(q->uuid)); + if (err != 0) + goto error; + + err = find_prefix_in_section(start, end, PREFIX_NOTAFTER, + tmp, sizeof(tmp)); + if (err != 0) { + long long usec; + + errno = 0; + usec = strtoll(tmp, NULL, 10); + if (errno != 0) + goto error; + + q->time.tv_sec = usec / 1000000; + q->time.tv_nsec = usec % 1000000 * 1000; + } + + err = find_prefix_in_section(start, end, PREFIX_SOCKET, + q->sock.sun_path, sizeof(q->sock.sun_path)); + if (err != 0) + goto error; + + munmap(file, st.st_size); + return q; + +error: + if (file) + munmap(file, st.st_size); + + free(q); + return NULL; +} diff --git a/src/plugins/askpassd/main.h b/src/plugins/askpassd/question.h similarity index 80% rename from src/plugins/askpassd/main.h rename to src/plugins/askpassd/question.h index f79fab1..ea73331 100644 --- a/src/plugins/askpassd/main.h +++ b/src/plugins/askpassd/question.h @@ -17,13 +17,18 @@ */ #include "list.h" + +#include #include -#include -#include +#include -struct key { +struct question { struct list list; - uint8_t key[256]; - ssize_t len; + char name[PATH_MAX]; char uuid[PATH_MAX]; + struct sockaddr_un sock; + struct timespec time; }; + +struct question * +question_new(const char *dir, const char *name);