libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
/*
|
2023-01-30 02:14:17 +05:30
|
|
|
* SPDX-FileCopyrightText: 2022, Alejandro Colomar <alx@kernel.org>
|
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
*
|
2023-01-30 02:14:17 +05:30
|
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
*/
|
|
|
|
|
2023-01-30 02:14:17 +05:30
|
|
|
|
2022-11-21 18:30:13 +05:30
|
|
|
#include <config.h>
|
|
|
|
|
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
#include <limits.h>
|
|
|
|
#include <readpassphrase.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#ident "$Id$"
|
|
|
|
|
|
|
|
#include "prototypes.h"
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(PASS_MAX)
|
|
|
|
#define PASS_MAX BUFSIZ
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* SYNOPSIS
|
|
|
|
* [[gnu::malloc(erase_pass)]]
|
|
|
|
* char *agetpass(const char *prompt);
|
|
|
|
*
|
|
|
|
* void erase_pass(char *pass);
|
|
|
|
*
|
|
|
|
* ARGUMENTS
|
|
|
|
* agetpass()
|
|
|
|
* prompt String to be printed before reading a password.
|
|
|
|
*
|
|
|
|
* erase_pass()
|
|
|
|
* pass password previously returned by agetpass().
|
|
|
|
*
|
|
|
|
* DESCRIPTION
|
|
|
|
* agetpass()
|
|
|
|
* This function is very similar to getpass(3). It has several
|
|
|
|
* advantages compared to getpass(3):
|
|
|
|
*
|
|
|
|
* - Instead of using a static buffer, agetpass() allocates memory
|
|
|
|
* through malloc(3). This makes the function thread-safe, and
|
|
|
|
* also reduces the visibility of the buffer.
|
|
|
|
*
|
|
|
|
* - agetpass() doesn't call realloc(3) internally. Some
|
|
|
|
* implementations of getpass(3), such as glibc, do that, as a
|
|
|
|
* consequence of calling getline(3). That's a bug in glibc,
|
|
|
|
* which allows leaking prefixes of passwords in freed memory.
|
|
|
|
*
|
|
|
|
* - agetpass() doesn't overrun the output buffer. If the input
|
|
|
|
* password is too long, it simply fails. Some implementations
|
|
|
|
* of getpass(3), share the same bug that gets(3) has.
|
|
|
|
*
|
|
|
|
* As soon as possible, the password obtained from agetpass() be
|
|
|
|
* erased by calling erase_pass(), to avoid possibly leaking the
|
|
|
|
* password.
|
|
|
|
*
|
|
|
|
* erase_pass()
|
|
|
|
* This function first clears the password, by calling
|
|
|
|
* explicit_bzero(3) (or an equivalent call), and then frees the
|
|
|
|
* allocated memory by calling free(3).
|
|
|
|
*
|
|
|
|
* NULL is a valid input pointer, and in such a case, this call is
|
|
|
|
* a no-op.
|
|
|
|
*
|
|
|
|
* RETURN VALUE
|
|
|
|
* agetpass() returns a newly allocated buffer containing the
|
|
|
|
* password on success. On error, errno is set to indicate the
|
|
|
|
* error, and NULL is returned.
|
|
|
|
*
|
|
|
|
* ERRORS
|
|
|
|
* agetpass()
|
|
|
|
* This function may fail for any errors that malloc(3) or
|
|
|
|
* readpassphrase(3) may fail, and in addition it may fail for the
|
|
|
|
* following errors:
|
|
|
|
*
|
|
|
|
* ENOBUFS
|
|
|
|
* The input password was longer than PASS_MAX.
|
|
|
|
*
|
|
|
|
* CAVEATS
|
|
|
|
* If a password is passed twice to erase_pass(), the behavior is
|
|
|
|
* undefined.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
agetpass(const char *prompt)
|
|
|
|
{
|
|
|
|
char *pass;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
pass = malloc(PASS_MAX);
|
|
|
|
if (pass == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (readpassphrase(prompt, pass, PASS_MAX, RPP_REQUIRE_TTY) == NULL)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
len = strlen(pass);
|
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
return pass;
|
|
|
|
|
|
|
|
if (pass[len - 1] != '\n') {
|
|
|
|
errno = ENOBUFS;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
pass[len - 1] = '\0';
|
|
|
|
|
|
|
|
return pass;
|
|
|
|
|
|
|
|
fail:
|
2023-02-02 00:59:29 +05:30
|
|
|
freezero(pass, PASS_MAX);
|
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
erase_pass(char *pass)
|
|
|
|
{
|
2023-02-02 00:59:29 +05:30
|
|
|
freezero(pass, PASS_MAX);
|
libmisc: agetpass(), erase_pass(): Add functions for getting passwords safely
There are several issues with getpass(3).
Many implementations of it share the same issues that the infamous
gets(3). In glibc it's not so terrible, since it's a wrapper
around getline(3). But it still has an important bug:
If the password is long enough, getline(3) will realloc(3) memory,
and prefixes of the password will be laying around in some
deallocated memory.
See the getpass(3) manual page for more details, and especially
the commit that marked it as deprecated, which links to a long
discussion in the linux-man@ mailing list.
So, readpassphrase(3bsd) is preferrable, which is provided by
libbsd on GNU systems. However, using readpassphrase(3) directly
is a bit verbose, so we can write our own wrapper with a simpler
interface similar to that of getpass(3).
One of the benefits of writing our own interface around
readpassphrase(3) is that we can hide there any checks that should
be done always and which would be error-prone to repeat every
time. For example, check that there was no truncation in the
password.
Also, use malloc(3) to get the buffer, instead of using a global
buffer. We're not using a multithreaded program (and it wouldn't
make sense to do so), but it's nice to know that the visibility of
our passwords is as limited as possible.
erase_pass() is a clean-up function that handles all clean-up
correctly, including zeroing the entire buffer, and then
free(3)ing the memory. By using [[gnu::malloc(erase_pass)]], we
make sure that we don't leak the buffers in any case, since the
compiler will be able to enforce clean up.
Link: <https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit?id=7ca189099d73bde954eed2d7fc21732bcc8ddc6b>
Reported-by: Christian Göttsche <cgzones@googlemail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
2022-09-27 01:52:24 +05:30
|
|
|
}
|