Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

agetpass(): Allocate on the stack (alloca(3)) #1191

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ libshadow_la_SOURCES = \
adds.c \
adds.h \
age.c \
agetpass.c \
agetpass.h \
alloc/calloc.c \
alloc/calloc.h \
alloc/malloc.c \
Expand Down Expand Up @@ -138,6 +136,8 @@ libshadow_la_SOURCES = \
pam_defs.h \
pam_pass.c \
pam_pass_non_interactive.c \
pass.c \
pass.h \
port.c \
port.h \
prefix_flag.c \
Expand Down
145 changes: 0 additions & 145 deletions lib/agetpass.c

This file was deleted.

23 changes: 0 additions & 23 deletions lib/agetpass.h

This file was deleted.

2 changes: 2 additions & 0 deletions lib/alloc/malloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

#include <config.h>

#include <alloca.h>
#include <stdlib.h>

#include "attr.h"


#define ALLOCA(n, type) ((type *) alloca(n * sizeof(type)))
#define MALLOC(n, type) \
( \
(type *) mallocarray(n, sizeof(type)) \
Expand Down
10 changes: 0 additions & 10 deletions lib/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,4 @@
# define shadow_getenv(name) getenv(name)
#endif

/*
* Maximum password length
*
* Consider that there is also limit in PAM (PAM_MAX_RESP_SIZE)
* currently set to 512.
*/
#if !defined(PASS_MAX)
#define PASS_MAX BUFSIZ - 1
#endif

#endif /* _DEFINES_H_ */
61 changes: 61 additions & 0 deletions lib/pass.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2022-2025, Alejandro Colomar <[email protected]>
// SPDX-License-Identifier: BSD-3-Clause


#include <config.h>

#include "pass.h"

#include <errno.h>
#include <readpassphrase.h>
#include <stddef.h>
#include <string.h>

#include "sizeof.h"
#include "string/memset/memzero.h"


#define READPASSPHRASE(prompt, buf, flags) \
( \
readpassphrase(prompt, buf, NITEMS(buf), flags) \
)


pass_t *
passzero(pass_t *pass)
{
if (pass == NULL)
return NULL;

return MEMZERO(*pass);
}


// readpassphrase(3), but detect truncation, and memzero() on error.
pass_t *
readpass(pass_t *pass, const char *restrict prompt, int flags)
{
size_t len;

/*
* Since we want to support passwords upto PASS_MAX, we need
* PASS_MAX bytes for the password itself, and one more byte for
* the terminating '\0'. We also want to detect truncation, and
* readpassphrase(3) doesn't detect it, so we need some trick.
* Let's add one more byte, and if the password uses it, it
* means the introduced password was longer than PASS_MAX.
*/
if (READPASSPHRASE(prompt, *pass, flags) == NULL)
goto fail;

len = strlen(*pass);
if (len == NITEMS(*pass) - 1) {
errno = ENOBUFS;
goto fail;
}

return pass;
fail:
MEMZERO(*pass);
return NULL;
}
46 changes: 46 additions & 0 deletions lib/pass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-FileCopyrightText: 2022-2025, Alejandro Colomar <[email protected]>
// SPDX-License-Identifier: BSD-3-Clause


#ifndef SHADOW_INCLUDE_LIB_PASS_H_
#define SHADOW_INCLUDE_LIB_PASS_H_


#include <config.h>

#include <limits.h>
#include <readpassphrase.h>
#include <stddef.h>
#include <stdio.h>

#include "alloc/malloc.h"
#include "attr.h"


// There is also a limit in PAM (PAM_MAX_RESP_SIZE), currently set to 512.
#ifndef PASS_MAX
# define PASS_MAX (BUFSIZ - 1)
#endif


// Similar to getpass(3), but free of its problems, and using alloca(3).
#define getpassa(prompt) getpass2(passalloca(), prompt)
#define getpassa_stdin() getpass2_stdin(passalloca())

// Similar to getpass(3), but free of its problems, and get the buffer in $1.
#define getpass2(buf, prompt) readpass(buf, prompt, RPP_REQUIRE_TTY)
#define getpass2_stdin(buf) readpass(buf, NULL, RPP_STDIN)

#define passalloca() ALLOCA(1, pass_t)


typedef typeof(char [PASS_MAX + 2]) pass_t;


pass_t *passzero(pass_t *pass);

ATTR_MALLOC(passzero)
pass_t *readpass(pass_t *pass, const char *restrict prompt, int flags);


#endif // include guard
16 changes: 8 additions & 8 deletions lib/pwauth.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
#include <sys/types.h>
#include <unistd.h>

#include "agetpass.h"
#include "defines.h"
#include "pass.h"
#include "prototypes.h"
#include "pwauth.h"
#include "getdef.h"
Expand Down Expand Up @@ -55,7 +55,7 @@ int pw_auth (const char *cipher,
{
int retval;
char prompt[1024];
char *clear = NULL;
pass_t *clear = NULL;
const char *cp;
const char *encrypted;

Expand Down Expand Up @@ -144,8 +144,8 @@ int pw_auth (const char *cipher,
#endif

SNPRINTF(prompt, cp, user);
clear = agetpass(prompt);
input = (clear == NULL) ? "" : clear;
clear = getpassa(prompt);
Fixed Show fixed Hide fixed
input = (clear == NULL) ? "" : *clear;
}

/*
Expand All @@ -171,9 +171,9 @@ int pw_auth (const char *cipher,
* -- AR 8/22/1999
*/
if ((0 != retval) && streq(input, "") && use_skey) {
erase_pass(clear);
clear = agetpass(prompt);
input = (clear == NULL) ? "" : clear;
passzero(clear);
clear = getpassa(prompt);
input = (clear == NULL) ? "" : *clear;
}

if ((0 != retval) && use_skey) {
Expand All @@ -187,7 +187,7 @@ int pw_auth (const char *cipher,
}
}
#endif
erase_pass(clear);
passzero(clear);

return retval;
}
Expand Down
Loading
Loading