Check pass when starting agent

And use O_RDONLY when it's possible.

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët 2020-05-29 15:17:33 +00:00
parent 9e35f4afc6
commit 7baf7e1a92

View file

@ -49,7 +49,7 @@ static struct {
char ctx_master[hydro_pwhash_CONTEXTBYTES]; char ctx_master[hydro_pwhash_CONTEXTBYTES];
char ctx_secret[hydro_secretbox_CONTEXTBYTES]; char ctx_secret[hydro_secretbox_CONTEXTBYTES];
char ctx_passwd[hydro_pwhash_CONTEXTBYTES]; char ctx_passwd[hydro_pwhash_CONTEXTBYTES];
int known_key; int pass_ok;
} s = { } s = {
.pipe = {-1, -1}, .pipe = {-1, -1},
.ctx_master = "MASTER", .ctx_master = "MASTER",
@ -203,38 +203,40 @@ s_ask_pass(void *buf, size_t size, const char *prompt)
} }
static int static int
s_open_secret(int use_tty) s_open_secret(int use_tty, int flags)
{ {
int fd = open(s.path, O_RDWR); int fd = open(s.path, flags);
if (fd == -1) switch (errno) { if (fd == -1) switch (errno) {
case ENOENT: s_fatal("Secret store %s doesn't exist", s.path); case ENOENT: s_fatal("Secret store %s doesn't exist", s.path);
default: s_fatal("%s: %s", s.path, strerror(errno)); default: s_fatal("%s: %s", s.path, strerror(errno));
} }
struct flock fl = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
};
if (fcntl(fd, F_SETLKW, &fl))
s_fatal("Unable to lock %s", s.path);
if (s_read(fd, s.hdr.buf, sizeof(s.hdr.buf)) != sizeof(s.hdr.buf)) if (s_read(fd, s.hdr.buf, sizeof(s.hdr.buf)) != sizeof(s.hdr.buf))
s_fatal("Unable to read %s", s.path); s_fatal("Unable to read %s", s.path);
if (s.hdr.version != S_VER_MAJOR) if (s.hdr.version != S_VER_MAJOR)
s_fatal("Unkown version %" PRIu8, s.hdr.version); s_fatal("Unkown version %" PRIu8, s.hdr.version);
if (flags == O_RDWR) {
struct flock fl = {
.l_type = F_WRLCK,
.l_whence = SEEK_SET,
};
if (fcntl(fd, F_SETLKW, &fl))
s_fatal("Unable to lock %s", s.path);
}
const char *agent = getenv(S_ENV_AGENT); const char *agent = getenv(S_ENV_AGENT);
int wfd = -1, rfd = -1; int wfd = -1, rfd = -1;
if (agent && sscanf(agent, "%d.%d", &wfd, &rfd) == 2 && if (agent && sscanf(agent, "%d.%d", &wfd, &rfd) == 2 &&
wfd >= 0 && rfd >= 0 && wfd >= 0 && rfd >= 0 &&
s_write(wfd, "", 1) == 1 && s_write(wfd, "", 1) == 1 &&
s_read(rfd, s.x.key, sizeof(s.x.key)) == sizeof(s.x.key)) s_read(rfd, s.x.key, sizeof(s.x.key)) == sizeof(s.x.key)) {
s.pass_ok = 1;
return fd; return fd;
}
if (!use_tty) if (!use_tty)
s_exit(0); s_exit(0);
@ -260,7 +262,7 @@ s_keylen(const char *str)
static void static void
s_print_keys(int use_tty) s_print_keys(int use_tty)
{ {
int fd = s_open_secret(use_tty); int fd = s_open_secret(use_tty, O_RDONLY);
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) { while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
if (hydro_secretbox_decrypt(&s.x.entry, if (hydro_secretbox_decrypt(&s.x.entry,
@ -276,25 +278,37 @@ s_print_keys(int use_tty)
static const char * static const char *
s_get_secret(int fd, const char *key, int create) s_get_secret(int fd, const char *key, int create)
{ {
size_t len = s_keylen(key); size_t len = key ? s_keylen(key) : 0;
while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) { while (s_read(fd, s.enc, sizeof(s.enc)) == sizeof(s.enc)) {
if (hydro_secretbox_decrypt(&s.x.entry, if (hydro_secretbox_decrypt(&s.x.entry,
s.enc, sizeof(s.enc), 0, s.enc, sizeof(s.enc), 0,
s.ctx_secret, s.x.key)) s.ctx_secret, s.x.key))
continue; continue;
if (hydro_equal(s.x.entry.msg, key, len + 1)) { if (key && hydro_equal(s.x.entry.msg, key, len + 1)) {
if (create) if (create)
s_fatal("Secret %s exists!", key); s_fatal("Secret %s exists!", key);
if (lseek(fd, -(off_t)sizeof(s.enc), SEEK_CUR) == (off_t)-1) if (lseek(fd, -(off_t)sizeof(s.enc), SEEK_CUR) == (off_t)-1)
s_fatal("seek: %s", strerror(errno)); s_fatal("seek: %s", strerror(errno));
return &s.x.entry.msg[len + 1]; return &s.x.entry.msg[len + 1];
} }
s.known_key = 1; s.pass_ok = 1;
} }
if (!create) if (key && !create)
s_fatal("Secret %s not found", key); s_fatal("Secret %s not found", key);
if (s.pass_ok)
return NULL;
char check[sizeof(s.x.key)];
s_ask_pass(check, sizeof(check),
"It's the first time you use this passphrase.\n"
"Please, retype it to confirm: ");
if (!hydro_equal(s.x.key, check, sizeof(check)))
s_fatal("Passphrases don't match!");
s.pass_ok = 1;
return NULL; return NULL;
} }
@ -393,18 +407,8 @@ s_do(int argc, char **argv, void *data)
return 0; return 0;
} }
int fd = s_open_secret(1); int fd = s_open_secret(1, O_RDWR);
const char *old = s_get_secret(fd, argv[1], op & s_op_create); const char *old = s_get_secret(fd, argv[1], op & s_op_create);
if (!old && !s.known_key) {
char check[sizeof(s.x.key)];
s_ask_pass(check, sizeof(check),
"It's the first time you use this passphrase.\n"
"Please, retype it to confirm: ");
if (!hydro_equal(s.x.key, check, sizeof(check)))
s_fatal("Passphrases don't match!");
}
unsigned char secret[S_ENTRYSIZE]; unsigned char secret[S_ENTRYSIZE];
size_t len = 0; size_t len = 0;
@ -439,7 +443,7 @@ s_show(int argc, char **argv, void *data)
return 0; return 0;
} }
int fd = s_open_secret(1); int fd = s_open_secret(1, O_RDONLY);
const char *secret = s_get_secret(fd, argv[1], 0); const char *secret = s_get_secret(fd, argv[1], 0);
if (secret) { if (secret) {
@ -458,7 +462,7 @@ s_pass(int argc, char **argv, void *data)
printf("Usage: %s KEY [SUBKEY...]\n", argv[0]); printf("Usage: %s KEY [SUBKEY...]\n", argv[0]);
return 0; return 0;
} }
close(s_open_secret(1)); close(s_open_secret(1, O_RDONLY));
uint8_t buf[hydro_pwhash_MASTERKEYBYTES]; uint8_t buf[hydro_pwhash_MASTERKEYBYTES];
uint8_t key[hydro_pwhash_MASTERKEYBYTES]; uint8_t key[hydro_pwhash_MASTERKEYBYTES];
@ -509,7 +513,9 @@ s_agent(int argc, char **argv, void *data)
if (getenv(S_ENV_AGENT)) if (getenv(S_ENV_AGENT))
s_fatal("Already running..."); s_fatal("Already running...");
close(s_open_secret(1)); int fd = s_open_secret(1, O_RDONLY);
s_get_secret(fd, NULL, 0);
close(fd);
int rfd[2], wfd[2]; int rfd[2], wfd[2];