login: add xgetpwnam()

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2016-10-14 13:21:17 +02:00
parent 302b7b65e4
commit 4f5f35fc83
5 changed files with 85 additions and 24 deletions

View File

@ -19,6 +19,7 @@ dist_noinst_HEADERS += \
include/fileutils.h \
include/idcache.h \
include/ismounted.h \
include/pwdutils.h \
include/linux_version.h \
include/list.h \
include/loopdev.h \

10
include/pwdutils.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef UTIL_LINUX_PWDUTILS_H
#define UTIL_LINUX_PWDUTILS_H
#include <sys/types.h>
#include <pwd.h>
extern struct passwd *xgetpwnam(const char *username, char **pwdbuf);
#endif /* UTIL_LINUX_PWDUTILS_H */

View File

@ -18,6 +18,7 @@ libcommon_la_SOURCES = \
lib/pager.c \
lib/parse-date.y \
lib/path.c \
lib/pwdutils.c \
lib/randutils.c \
lib/setproctitle.c \
lib/strutils.c \
@ -74,6 +75,7 @@ check_PROGRAMS += \
test_colors \
test_fileutils \
test_ismounted \
test_pwdutils \
test_mangle \
test_randutils \
test_strutils \
@ -149,3 +151,6 @@ test_canonicalize_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_CANONICALIZE
test_timeutils_SOURCES = lib/timeutils.c lib/strutils.c
test_timeutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM_TIMEUTILS
test_pwdutils_SOURCES = lib/pwdutils.c
test_pwdutils_CFLAGS = $(AM_CFLAGS) -DTEST_PROGRAM

64
lib/pwdutils.c Normal file
View File

@ -0,0 +1,64 @@
#include <stdlib.h>
#include "c.h"
#include "pwdutils.h"
#include "xalloc.h"
/* Returns allocated passwd and allocated pwdbuf to store passwd strings
* fields. In case of error returns NULL and set errno, for unknown user set
* errno to EINVAL
*/
struct passwd *xgetpwnam(const char *username, char **pwdbuf)
{
struct passwd *pwd = NULL, *res = NULL;
int rc;
if (!pwdbuf || !username)
return NULL;
*pwdbuf = xmalloc(UL_GETPW_BUFSIZ);
pwd = xcalloc(1, sizeof(struct passwd));
errno = 0;
rc = getpwnam_r(username, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
if (rc != 0) {
errno = rc;
goto failed;
}
if (!res) {
errno = EINVAL;
goto failed;
}
return pwd;
failed:
free(pwd);
free(*pwdbuf);
return NULL;
}
#ifdef TEST_PROGRAM
int main(int argc, char *argv[])
{
char *pwdbuf = NULL;
struct passwd *pwd = NULL;
if (argc != 2) {
fprintf(stderr, "usage: %s <username>\n", argv[0]);
return EXIT_FAILURE;
}
pwd = xgetpwnam(argv[1], &pwdbuf);
if (!pwd)
err(EXIT_FAILURE, "failed to get %s pwd entry", argv[1]);
printf("Username: %s\n", pwd->pw_name);
printf("UID: %d\n", pwd->pw_uid);
printf("HOME: %s\n", pwd->pw_dir);
printf("GECO: %s\n", pwd->pw_gecos);
free(pwd);
free(pwdbuf);
return EXIT_SUCCESS;
}
#endif /* TEST_PROGRAM */

View File

@ -77,6 +77,7 @@
#include "all-io.h"
#include "fileutils.h"
#include "ttyutils.h"
#include "pwdutils.h"
#include "logindefs.h"
@ -107,6 +108,7 @@ struct login_context {
char *username; /* from command line or PAM */
struct passwd *pwd; /* user info */
char *pwdbuf; /* pwd strings */
pam_handle_t *pamh; /* PAM handler */
struct pam_conv conv; /* PAM conversation */
@ -652,26 +654,6 @@ static void log_syslog(struct login_context *cxt)
}
}
static struct passwd *get_passwd_entry(const char *username,
char **pwdbuf,
struct passwd *pwd)
{
struct passwd *res = NULL;
int x;
if (!pwdbuf || !username)
return NULL;
*pwdbuf = xrealloc(*pwdbuf, UL_GETPW_BUFSIZ);
x = getpwnam_r(username, pwd, *pwdbuf, UL_GETPW_BUFSIZ, &res);
if (!res) {
errno = x;
return NULL;
}
return res;
}
/* encapsulate stupid "void **" pam_get_item() API */
static int loginpam_get_username(pam_handle_t *pamh, char **name)
{
@ -1129,9 +1111,7 @@ int main(int argc, char **argv)
int childArgc = 0;
int retcode;
struct sigaction act;
char *pwdbuf = NULL;
struct passwd *pwd = NULL, _pwd;
struct passwd *pwd;
struct login_context cxt = {
.tty_mode = TTY_MODE, /* tty chmod() */
@ -1243,7 +1223,8 @@ int main(int argc, char **argv)
*/
loginpam_acct(&cxt);
if (!(cxt.pwd = get_passwd_entry(cxt.username, &pwdbuf, &_pwd))) {
cxt.pwd = xgetpwnam(cxt.username, &cxt.pwdbuf);
if (!cxt.pwd) {
warnx(_("\nSession setup problem, abort."));
syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."),
cxt.username, __FUNCTION__, __LINE__);