[linux-pam] Cleanups of pam_pwhistory code. Make opasswd entry parsing more robust.
by Tomáš Mráz
commit ff7c230341fc4bd2266b9ddaf39d83683f12c040
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Wed Jun 15 20:48:59 2011 +0200
Cleanups of pam_pwhistory code. Make opasswd entry parsing more robust.
* modules/pam_pwhistory/opasswd.c (check_old_password): Do not
needlessly call strdupa().
(save_old_password): Avoid memleaks in error paths. Avoid memleak of
buf. Make the opasswd entry parsing more robust.
* modules/pam_pwhistory/pam_pwhistory.8.xml: Document the
special meaning of remember=0.
ChangeLog | 9 ++++-
modules/pam_pwhistory/opasswd.c | 57 +++++++++++++++++------------
modules/pam_pwhistory/pam_pwhistory.8.xml | 4 ++-
3 files changed, 44 insertions(+), 26 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7642831..b3c499a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,14 @@
* modules/pam_sepermit/pam_sepermit.c (check_running): Avoid
leaking memory and dir handle on realloc failure.
- (sepermit_unlock) Cast fcntl() and close() calls to void.
+ (sepermit_unlock): Cast fcntl() and close() calls to void.
+
+ * modules/pam_pwhistory/opasswd.c (check_old_password): Do not
+ needlessly call strdupa().
+ (save_old_password): Avoid memleaks in error paths. Avoid memleak of
+ buf. Make the opasswd entry parsing more robust.
+ * modules/pam_pwhistory/pam_pwhistory.8.xml: Document the
+ special meaning of remember=0.
2011-06-14 Thorsten Kukuk <kukuk(a)thkukuk.de>
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c
index f045555..738483a 100644
--- a/modules/pam_pwhistory/opasswd.c
+++ b/modules/pam_pwhistory/opasswd.c
@@ -181,15 +181,13 @@ check_old_password (pam_handle_t *pamh, const char *user,
fclose (oldpf);
- if (found)
+ if (found && entry.old_passwords)
{
const char delimiters[] = ",";
char *running;
char *oldpass;
- running = strdupa (entry.old_passwords);
- if (running == NULL)
- return PAM_BUF_ERR;
+ running = entry.old_passwords;
do {
oldpass = strsep (&running, delimiters);
@@ -311,8 +309,12 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
buflen = DEFAULT_BUFLEN;
buf = malloc (buflen);
if (buf == NULL)
- return PAM_BUF_ERR;
-
+ {
+ fclose (oldpf);
+ fclose (newpf);
+ retval = PAM_BUF_ERR;
+ goto error_opasswd;
+ }
}
buf[0] = '\0';
fgets (buf, buflen - 1, oldpf);
@@ -322,7 +324,12 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
cp = buf;
save = strdup (buf); /* Copy to write the original data back. */
if (save == NULL)
- return PAM_BUF_ERR;
+ {
+ fclose (oldpf);
+ fclose (newpf);
+ retval = PAM_BUF_ERR;
+ goto error_opasswd;
+ }
if (n < 1)
break;
@@ -351,31 +358,30 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
found = 1;
/* Don't save the current password twice */
- if (entry.old_passwords)
+ if (entry.old_passwords && entry.old_passwords[0] != '\0')
{
- /* there is only one password */
- if (strcmp (entry.old_passwords, oldpass) == 0)
- goto write_old_data;
- else
+ char *last = entry.old_passwords;
+
+ cp = entry.old_passwords;
+ entry.count = 1; /* Don't believe the count */
+ while ((cp = strchr (cp, ',')) != NULL)
{
- /* check last entry */
- cp = strstr (entry.old_passwords, oldpass);
-
- if (cp && strcmp (cp, oldpass) == 0)
- { /* the end is the same, check that there
- is a "," before. */
- --cp;
- if (*cp == ',')
- goto write_old_data;
- }
+ entry.count++;
+ last = ++cp;
}
+
+ /* compare the last password */
+ if (strcmp (last, oldpass) == 0)
+ goto write_old_data;
}
+ else
+ entry.count = 0;
/* increase count. */
entry.count++;
/* check that we don't remember to many passwords. */
- while (entry.count > howmany)
+ while (entry.count > howmany && entry.count > 1)
{
char *p = strpbrk (entry.old_passwords, ",");
if (p != NULL)
@@ -383,12 +389,13 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
entry.count--;
}
- if (entry.old_passwords == NULL)
+ if (entry.count == 1)
{
if (asprintf (&out, "%s:%s:%d:%s\n",
entry.user, entry.uid, entry.count,
oldpass) < 0)
{
+ free (save);
retval = PAM_AUTHTOK_ERR;
fclose (oldpf);
fclose (newpf);
@@ -401,6 +408,7 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
entry.user, entry.uid, entry.count,
entry.old_passwords, oldpass) < 0)
{
+ free (save);
retval = PAM_AUTHTOK_ERR;
fclose (oldpf);
fclose (newpf);
@@ -493,6 +501,7 @@ save_old_password (pam_handle_t *pamh, const char *user, uid_t uid,
rename (opasswd_tmp, OLD_PASSWORDS_FILE);
error_opasswd:
unlink (opasswd_tmp);
+ free (buf);
return retval;
}
diff --git a/modules/pam_pwhistory/pam_pwhistory.8.xml b/modules/pam_pwhistory/pam_pwhistory.8.xml
index 7696353..9e1056b 100644
--- a/modules/pam_pwhistory/pam_pwhistory.8.xml
+++ b/modules/pam_pwhistory/pam_pwhistory.8.xml
@@ -105,7 +105,9 @@
<para>
The last <replaceable>N</replaceable> passwords for each
user are saved in <filename>/etc/security/opasswd</filename>.
- The default is <emphasis>10</emphasis>.
+ The default is <emphasis>10</emphasis>. Value of
+ <emphasis>0</emphasis> makes the module to keep the existing
+ contents of the <filename>opasswd</filename> file unchanged.
</para>
</listitem>
</varlistentry>
13 years
[linux-pam] Avoid leaking memory and dir handle on realloc failure.
by Tomáš Mráz
commit 62748f7df90225dc0635944ef59e6e4754c302c0
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Wed Jun 15 18:48:12 2011 +0200
Avoid leaking memory and dir handle on realloc failure.
ChangeLog | 6 ++++++
modules/pam_sepermit/pam_sepermit.c | 12 +++++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index d8c954d..7642831 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-06-15 Tomas Mraz <tm(a)t8m.info>
+
+ * modules/pam_sepermit/pam_sepermit.c (check_running): Avoid
+ leaking memory and dir handle on realloc failure.
+ (sepermit_unlock) Cast fcntl() and close() calls to void.
+
2011-06-14 Thorsten Kukuk <kukuk(a)thkukuk.de>
* configure.in: Check for libtirpc by default.
diff --git a/modules/pam_sepermit/pam_sepermit.c b/modules/pam_sepermit/pam_sepermit.c
index 8b2360b..4879b68 100644
--- a/modules/pam_sepermit/pam_sepermit.c
+++ b/modules/pam_sepermit/pam_sepermit.c
@@ -117,6 +117,7 @@ check_running (pam_handle_t *pamh, uid_t uid, int killall, int debug)
max_pids = 256;
pid_table = malloc(max_pids * sizeof (pid_t));
if (!pid_table) {
+ (void)closedir(dir);
pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
return -1;
}
@@ -126,10 +127,15 @@ check_running (pam_handle_t *pamh, uid_t uid, int killall, int debug)
continue;
if (pids == max_pids) {
- if (!(pid_table = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
+ pid_t *npt;
+
+ if (!(npt = realloc(pid_table, 2*pids*sizeof(pid_t)))) {
+ free(pid_table);
+ (void)closedir(dir);
pam_syslog(pamh, LOG_CRIT, "Memory allocation error");
return -1;
}
+ pid_table = npt;
max_pids *= 2;
}
pid_table[pids++] = pid;
@@ -175,8 +181,8 @@ sepermit_unlock(pam_handle_t *pamh, void *plockfd, int error_status UNUSED)
while(check_running(pamh, lockfd->uid, 1, lockfd->debug) > 0)
continue;
- fcntl(lockfd->fd, F_SETLK, &fl);
- close(lockfd->fd);
+ (void)fcntl(lockfd->fd, F_SETLK, &fl);
+ (void)close(lockfd->fd);
free(lockfd);
}
13 years
[linux-pam] Fix typo
by kukuk
commit 3299b9a05f3928b5a535512fcae1bf2769ea2f22
Author: Thorsten Kukuk <kukuk(a)thkukuk.de>
Date: Tue Jun 14 16:08:15 2011 +0200
Fix typo
ChangeLog | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8d6bfd2..d8c954d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,6 @@
2011-06-14 Thorsten Kukuk <kukuk(a)thkukuk.de>
- * configure.in: Check for libtirpc bye default.
+ * configure.in: Check for libtirpc by default.
* libpam/Makefile.am: Add support for libtirpc.
* modules/pam_access/Makefile.am: Likewise.
* modules/pam_unix/Makefile.am: Likewise.
13 years
[linux-pam] 2011-06-14 Thorsten Kukuk <kukuk@thkukuk.de>
by kukuk
commit 0fda81ee5bdc656554d55fb8d6f40c39bae3a3bf
Author: Thorsten Kukuk <kukuk(a)thkukuk.de>
Date: Tue Jun 14 15:28:05 2011 +0200
2011-06-14 Thorsten Kukuk <kukuk(a)thkukuk.de>
* configure.in: Check for libtirpc bye default.
* libpam/Makefile.am: Add support for libtirpc.
* modules/pam_access/Makefile.am: Likewise.
* modules/pam_unix/Makefile.am: Likewise.
* modules/pam_unix/pam_unix_passwd.c: Change ifdefs for
new libtirpc support.
* modules/pam_unix/yppasswd_xdr.c: Only compile if we have rpc/rpc.h.
ChangeLog | 10 +++++++
configure.in | 45 +++++++++++++++++++++++++++------
libpam/Makefile.am | 3 +-
modules/pam_access/Makefile.am | 4 +-
modules/pam_unix/Makefile.am | 5 ++-
modules/pam_unix/pam_unix_passwd.c | 48 ++++++++++++++++++++++-------------
modules/pam_unix/yppasswd_xdr.c | 4 +++
7 files changed, 87 insertions(+), 32 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 299b316..8d6bfd2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-06-14 Thorsten Kukuk <kukuk(a)thkukuk.de>
+
+ * configure.in: Check for libtirpc bye default.
+ * libpam/Makefile.am: Add support for libtirpc.
+ * modules/pam_access/Makefile.am: Likewise.
+ * modules/pam_unix/Makefile.am: Likewise.
+ * modules/pam_unix/pam_unix_passwd.c: Change ifdefs for
+ new libtirpc support.
+ * modules/pam_unix/yppasswd_xdr.c: Only compile if we have rpc/rpc.h.
+
2011-06-13 Tomas Mraz <tm(a)t8m.info>
* modules/pam_securetty/pam_securetty.c (securetty_perform_check): Test
diff --git a/configure.in b/configure.in
index d09d753..80f9ee9 100644
--- a/configure.in
+++ b/configure.in
@@ -441,12 +441,39 @@ fi
AC_SUBST(LIBDB)
AM_CONDITIONAL([HAVE_LIBDB], [test ! -z "$LIBDB"])
-AC_CHECK_LIB([nsl],[yp_get_default_domain], LIBNSL="-lnsl", LIBNSL="")
-BACKUP_LIBS=$LIBS
-LIBS="$LIBS $LIBNSL"
-AC_CHECK_FUNCS(yp_get_default_domain getdomainname innetgr yperr_string yp_master yp_bind yp_match yp_unbind)
-LIBS=$BACKUP_LIBS
-AC_SUBST(LIBNSL)
+AC_ARG_ENABLE([nis],
+ AS_HELP_STRING([-disable-nis], [Disable building NIS/YP support in pam_unix and pam_access]))
+
+AS_IF([test "x$enable_nis" != "xno"], [
+ CFLAGS=$old_CFLAGS
+ LIBS=$old_LIBS
+
+ dnl if there's libtirpc available, prefer that over the system
+ dnl implementation.
+ PKG_CHECK_MODULES([libtirpc], [libtirpc], [
+ CFLAGS="$CFLAGS $libtirpc_CFLAGS"
+ LIBS="$LIBS $libtirpc_LIBS"
+ ], [:;])
+
+ AC_SEARCH_LIBS([yp_get_default_domain], [nsl])
+
+ AC_CHECK_FUNCS([yp_get_default_domain yperr_string yp_master yp_bind yp_match yp_unbind])
+ AC_CHECK_HEADERS([rpc/rpc.h rpcsvc/ypclnt.h rpcsvc/yp_prot.h])
+ AC_CHECK_DECLS([getrpcport], , , [
+ #if HAVE_RPC_RPC_H
+ # include <rpc/rpc.h>
+ #endif
+ ])
+
+ NIS_CFLAGS="${CFLAGS%${old_CFLAGS}}"
+ NIS_LIBS="${LIBS%${old_LIBS}}"
+
+ CFLAGS="$old_CFLAGS"
+ LIBS="$old_LIBS"
+])
+
+AC_SUBST([NIS_CFLAGS])
+AC_SUBST([NIS_LIBS])
AC_ARG_ENABLE([selinux],
AS_HELP_STRING([--disable-selinux],[do not use SELinux]),
@@ -471,7 +498,7 @@ dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
-AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/file.h sys/ioctl.h sys/time.h syslog.h net/if.h termio.h unistd.h sys/fsuid.h inittypes.h rpcsvc/ypclnt.h rpcsvc/yp_prot.h)
+AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/file.h sys/ioctl.h sys/time.h syslog.h net/if.h termio.h unistd.h sys/fsuid.h inittypes.h)
dnl For module/pam_lastlog
AC_CHECK_HEADERS(lastlog.h utmp.h utmpx.h)
@@ -491,11 +518,11 @@ AC_TYPE_GETGROUPS
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS(fseeko gethostname gettimeofday lckpwdf mkdir select)
+AC_CHECK_FUNCS(fseeko getdomainname gethostname gettimeofday lckpwdf mkdir select)
AC_CHECK_FUNCS(strcspn strdup strspn strstr strtol uname)
AC_CHECK_FUNCS(getutent_r getpwnam_r getpwuid_r getgrnam_r getgrgid_r getspnam_r)
AC_CHECK_FUNCS(getgrouplist getline getdelim)
-AC_CHECK_FUNCS(inet_ntop inet_pton ruserok_af)
+AC_CHECK_FUNCS(inet_ntop inet_pton innetgr ruserok_af)
AC_CHECK_FUNCS(unshare, [UNSHARE=yes], [UNSHARE=no])
AM_CONDITIONAL([HAVE_UNSHARE], [test "$UNSHARE" = yes])
diff --git a/libpam/Makefile.am b/libpam/Makefile.am
index 3c7ae1d..f7e6c25 100644
--- a/libpam/Makefile.am
+++ b/libpam/Makefile.am
@@ -25,7 +25,8 @@ libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) @LIBDL@
if STATIC_MODULES
libpam_la_LIBADD += $(shell ls ../modules/pam_*/*.lo) \
- @LIBDB@ @LIBCRYPT@ @LIBNSL@ @LIBCRACK@ -lutil
+ @LIBDB@ @LIBCRYPT@ $(NIS_LIBS) @LIBCRACK@ -lutil
+ AM_CFLAGS += $(NIS_CFLAGS)
endif
if HAVE_VERSIONING
libpam_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libpam.map
diff --git a/modules/pam_access/Makefile.am b/modules/pam_access/Makefile.am
index b4fea7d..89222b5 100644
--- a/modules/pam_access/Makefile.am
+++ b/modules/pam_access/Makefile.am
@@ -15,14 +15,14 @@ securelibdir = $(SECUREDIR)
secureconfdir = $(SCONFIGDIR)
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
- -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\"
+ -DPAM_ACCESS_CONFIG=\"$(SCONFIGDIR)/access.conf\" $(NIS_CFLAGS)
AM_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
AM_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
securelib_LTLIBRARIES = pam_access.la
-pam_access_la_LIBADD = -L$(top_builddir)/libpam -lpam @LIBNSL@
+pam_access_la_LIBADD = -L$(top_builddir)/libpam -lpam $(NIS_LIBS)
secureconf_DATA = access.conf
diff --git a/modules/pam_unix/Makefile.am b/modules/pam_unix/Makefile.am
index 44b37e9..ba77d39 100644
--- a/modules/pam_unix/Makefile.am
+++ b/modules/pam_unix/Makefile.am
@@ -18,7 +18,8 @@ secureconfdir = $(SCONFIGDIR)
AM_CFLAGS = -I$(top_srcdir)/libpam/include -I$(top_srcdir)/libpamc/include \
-DCHKPWD_HELPER=\"$(sbindir)/unix_chkpwd\" \
- -DUPDATE_HELPER=\"$(sbindir)/unix_update\"
+ -DUPDATE_HELPER=\"$(sbindir)/unix_update\" \
+ $(NIS_CFLAGS)
if HAVE_LIBSELINUX
AM_CFLAGS += -D"WITH_SELINUX"
@@ -28,7 +29,7 @@ pam_unix_la_LDFLAGS = -no-undefined -avoid-version -module
if HAVE_VERSIONING
pam_unix_la_LDFLAGS += -Wl,--version-script=$(srcdir)/../modules.map
endif
-pam_unix_la_LIBADD = @LIBNSL@ -L$(top_builddir)/libpam -lpam \
+pam_unix_la_LIBADD = $(NIS_LIBS) -L$(top_builddir)/libpam -lpam \
@LIBCRYPT@ @LIBSELINUX@
securelib_LTLIBRARIES = pam_unix.la
diff --git a/modules/pam_unix/pam_unix_passwd.c b/modules/pam_unix/pam_unix_passwd.c
index 320bc54..631df31 100644
--- a/modules/pam_unix/pam_unix_passwd.c
+++ b/modules/pam_unix/pam_unix_passwd.c
@@ -54,13 +54,6 @@
#include <ctype.h>
#include <sys/time.h>
#include <sys/stat.h>
-#include <rpc/rpc.h>
-#ifdef HAVE_RPCSVC_YP_PROT_H
-#include <rpcsvc/yp_prot.h>
-#endif
-#ifdef HAVE_RPCSVC_YPCLNT_H
-#include <rpcsvc/ypclnt.h>
-#endif
#include <signal.h>
#include <errno.h>
@@ -76,16 +69,33 @@
#include <security/pam_ext.h>
#include <security/pam_modutil.h>
-#include "yppasswd.h"
#include "md5.h"
#include "support.h"
#include "passverify.h"
#include "bigcrypt.h"
-#if !((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
+#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER
+# define HAVE_NIS
+#endif
+
+#ifdef HAVE_NIS
+# include <rpc/rpc.h>
+
+# if HAVE_RPCSVC_YP_PROT_H
+# include <rpcsvc/yp_prot.h>
+# endif
+
+# if HAVE_RPCSVC_YPCLNT_H
+# include <rpcsvc/ypclnt.h>
+# endif
+
+# include "yppasswd.h"
+
+# if !HAVE_DECL_GETRPCPORT
extern int getrpcport(const char *host, unsigned long prognum,
unsigned long versnum, unsigned int proto);
-#endif /* GNU libc 2.1 */
+# endif /* GNU libc 2.1 */
+#endif
/*
How it works:
@@ -102,9 +112,9 @@ extern int getrpcport(const char *host, unsigned long prognum,
#define MAX_PASSWD_TRIES 3
+#ifdef HAVE_NIS
static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
{
-#if (defined(HAVE_YP_GET_DEFAULT_DOMAIN) || defined(HAVE_GETDOMAINNAME)) && defined(HAVE_YP_MASTER)
char *master;
char *domainname;
int port, err;
@@ -151,14 +161,8 @@ static char *getNISserver(pam_handle_t *pamh, unsigned int ctrl)
master, port);
}
return master;
-#else
- if (on(UNIX_DEBUG, ctrl)) {
- pam_syslog(pamh, LOG_DEBUG, "getNISserver: No NIS support available");
- }
-
- return NULL;
-#endif
}
+#endif
#ifdef WITH_SELINUX
@@ -326,6 +330,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho,
}
if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) {
+#ifdef HAVE_NIS
if ((master=getNISserver(pamh, ctrl)) != NULL) {
struct timeval timeout;
struct yppasswd yppwd;
@@ -391,6 +396,13 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho,
} else {
retval = PAM_TRY_AGAIN;
}
+#else
+ if (on(UNIX_DEBUG, ctrl)) {
+ pam_syslog(pamh, LOG_DEBUG, "No NIS support available");
+ }
+
+ retval = PAM_TRY_AGAIN;
+#endif
}
if (_unix_comesfromsource(pamh, forwho, 1, 0)) {
diff --git a/modules/pam_unix/yppasswd_xdr.c b/modules/pam_unix/yppasswd_xdr.c
index 0b95b82..f2b86a5 100644
--- a/modules/pam_unix/yppasswd_xdr.c
+++ b/modules/pam_unix/yppasswd_xdr.c
@@ -12,6 +12,8 @@
#include "config.h"
+#ifdef HAVE_RPC_RPC_H
+
#include <rpc/rpc.h>
#include "yppasswd.h"
@@ -34,3 +36,5 @@ xdr_yppasswd(XDR * xdrs, yppasswd * objp)
return xdr_string(xdrs, &objp->oldpass, ~0)
&& xdr_xpasswd(xdrs, &objp->newpw);
}
+
+#endif
13 years
[linux-pam] Test also whether the tty is in the /sys/class/tty/console/active file.
by Tomáš Mráz
commit cda7bd483b42a39157e69271fa2211d7e89944dc
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Mon Jun 13 20:27:18 2011 +0200
Test also whether the tty is in the /sys/class/tty/console/active file.
ChangeLog | 7 ++++++
modules/pam_securetty/pam_securetty.8.xml | 8 ++++--
modules/pam_securetty/pam_securetty.c | 33 ++++++++++++++++++++++++++++-
3 files changed, 44 insertions(+), 4 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index bcd456c..299b316 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2011-06-13 Tomas Mraz <tm(a)t8m.info>
+
+ * modules/pam_securetty/pam_securetty.c (securetty_perform_check): Test
+ also whether the tty is in the /sys/class/tty/console/active file.
+ * modules/pam_securetty/pam_securetty.8.xml: Document the new check of
+ /sys/class/tty/console/active/file.
+
2011-06-07 Tomas Mraz <tm(a)t8m.info>
* modules/pam_namespace/pam_namespace.c (root_shared): New
diff --git a/modules/pam_securetty/pam_securetty.8.xml b/modules/pam_securetty/pam_securetty.8.xml
index c5d6c5f..48215f5 100644
--- a/modules/pam_securetty/pam_securetty.8.xml
+++ b/modules/pam_securetty/pam_securetty.8.xml
@@ -35,7 +35,8 @@
to make sure that <filename>/etc/securetty</filename> is a plain
file and not world writable. It will also allow root logins on
the tty specified with <option>console=</option> switch on the
- kernel command line.
+ kernel command line and on ttys from the
+ <filename>/sys/class/tty/console/active</filename>.
</para>
<para>
This module has no effect on non-root users and requires that the
@@ -70,8 +71,9 @@
<listitem>
<para>
Do not automatically allow root logins on the kernel console
- device, as specified on the kernel command line, if it is
- not also specified in the <filename>/etc/securetty</filename> file.
+ device, as specified on the kernel command line or by the sys file,
+ if it is not also specified in the
+ <filename>/etc/securetty</filename> file.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_securetty/pam_securetty.c b/modules/pam_securetty/pam_securetty.c
index 99c6371..4e97ef5 100644
--- a/modules/pam_securetty/pam_securetty.c
+++ b/modules/pam_securetty/pam_securetty.c
@@ -3,6 +3,7 @@
#define SECURETTY_FILE "/etc/securetty"
#define TTY_PREFIX "/dev/"
#define CMDLINE_FILE "/proc/cmdline"
+#define CONSOLEACTIVE_FILE "/sys/class/tty/console/active"
/*
* by Elliot Lee <sopwith(a)redhat.com>, Red Hat Software.
@@ -169,7 +170,7 @@ securetty_perform_check (pam_handle_t *pamh, int ctrl,
if (p > line && p[-1] != ' ')
continue;
- /* Ist this our console? */
+ /* Is this our console? */
if (strncmp(p + 8, uttyname, strlen(uttyname)))
continue;
@@ -182,6 +183,36 @@ securetty_perform_check (pam_handle_t *pamh, int ctrl,
}
}
}
+ if (retval && !(ctrl & PAM_NOCONSOLE_ARG)) {
+ FILE *consoleactivefile;
+
+ /* Allow access from the active console */
+ consoleactivefile = fopen(CONSOLEACTIVE_FILE, "r");
+
+ if (consoleactivefile != NULL) {
+ char line[LINE_MAX], *p, *n;
+
+ line[0] = 0;
+ p = fgets(line, sizeof(line), consoleactivefile);
+ fclose(consoleactivefile);
+
+ if (p) {
+ /* remove the newline character at end */
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = 0;
+
+ for (n = p; n != NULL; p = n+1) {
+ if ((n = strchr(p, ' ')) != NULL)
+ *n = '\0';
+
+ if (strcmp(p, uttyname) == 0) {
+ retval = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
if (retval) {
pam_syslog(pamh, LOG_WARNING, "access denied: tty '%s' is not secure !",
13 years
[linux-pam] Detect the shared / mount and enable private mounts based on that.
by Tomáš Mráz
commit 2cd2fb864a52e71a5f6c15aea1cc7e953674aeb6
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Tue Jun 7 17:22:30 2011 +0200
Detect the shared / mount and enable private mounts based on that.
ChangeLog | 9 +++++
modules/pam_namespace/pam_namespace.8.xml | 7 +++-
modules/pam_namespace/pam_namespace.c | 51 +++++++++++++++++++++++++++++
3 files changed, 65 insertions(+), 2 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 836804b..bcd456c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-06-07 Tomas Mraz <tm(a)t8m.info>
+
+ * modules/pam_namespace/pam_namespace.c (root_shared): New
+ function to detect shared / mount.
+ (pam_sm_open_session): Call the root_shared() and enable
+ private mounts based on that.
+ * modules/pam_namespace/pam_namespace.8.xml: Document the
+ automatic detection of shared / mount.
+
2011-06-06 Tomas Mraz <tm(a)t8m.info>
* modules/pam_group/pam_group.c (shift_bytes): Removed.
diff --git a/modules/pam_namespace/pam_namespace.8.xml b/modules/pam_namespace/pam_namespace.8.xml
index f0ebe2c..48021c8 100644
--- a/modules/pam_namespace/pam_namespace.8.xml
+++ b/modules/pam_namespace/pam_namespace.8.xml
@@ -243,11 +243,14 @@
</term>
<listitem>
<para>
- This option should be used on systems where the / mount point and
+ This option can be used on systems where the / mount point or
its submounts are made shared (for example with a
<command>mount --make-rshared /</command> command).
The module will make the polyinstantiated directory mount points
- private.
+ private. Normally the pam_namespace will try to detect the
+ shared / mount point and make the polyinstantiated directories
+ private automatically. This option has to be used just when
+ only a subtree is shared and / is not.
</para>
</listitem>
</varlistentry>
diff --git a/modules/pam_namespace/pam_namespace.c b/modules/pam_namespace/pam_namespace.c
index d5a2d78..4a99184 100644
--- a/modules/pam_namespace/pam_namespace.c
+++ b/modules/pam_namespace/pam_namespace.c
@@ -1890,6 +1890,53 @@ static int ctxt_based_inst_needed(void)
}
#endif
+static int root_shared(void)
+{
+ FILE *f;
+ char *line = NULL;
+ size_t n = 0;
+ int rv = 0;
+
+ f = fopen("/proc/self/mountinfo", "r");
+
+ if (f == NULL)
+ return 0;
+
+ while(getline(&line, &n, f) != -1) {
+ char *l;
+ char *sptr;
+ int i;
+
+ l = line;
+ sptr = NULL;
+ for (i = 0; i < 7; i++) {
+ char *tok;
+
+ tok = strtok_r(l, " ", &sptr);
+ l = NULL;
+ if (tok == NULL)
+ /* next mountinfo line */
+ break;
+
+ if (i == 4 && strcmp(tok, "/") != 0)
+ /* next mountinfo line */
+ break;
+
+ if (i == 6) {
+ if (strncmp(tok, "shared:", 7) == 0)
+ /* there might be more / mounts, the last one counts */
+ rv = 1;
+ else
+ rv = 0;
+ }
+ }
+ }
+
+ free(line);
+ fclose(f);
+
+ return rv;
+}
static int get_user_data(struct instance_data *idata)
{
@@ -2002,6 +2049,10 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags UNUSED,
if (retval != PAM_SUCCESS)
return retval;
+ if (root_shared()) {
+ idata.flags |= PAMNS_MOUNT_PRIVATE;
+ }
+
/*
* Parse namespace configuration file which lists directories to
* polyinstantiate, directory where instance directories are to
13 years
[linux-pam] Define the MS_PRIVATE and MS_REC flags if they are not in sys/mount.h.
by Tomáš Mráz
commit c99be5959bc7e7b407f7dd9ba6637f8fbb6c9249
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Mon Jun 6 18:22:32 2011 +0200
Define the MS_PRIVATE and MS_REC flags if they are not in sys/mount.h.
ChangeLog | 3 +++
modules/pam_namespace/pam_namespace.h | 8 ++++++++
2 files changed, 11 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index b0cb53a..836804b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,9 @@
(check_account): read_field() now uses state information. No
extra read_field() call at the end of configuration line.
+ * modules/pam_namespace/pam_namespace.h: Define the MS_PRIVATE and
+ MS_REC flags if they are not in sys/mount.h.
+
2011-06-06 Nguyễn Thái Ngọc Duy <pclouds(a)gmail.com>
* po/LINGUAS: Add vietnamese.
diff --git a/modules/pam_namespace/pam_namespace.h b/modules/pam_namespace/pam_namespace.h
index 7b39068..c49995c 100644
--- a/modules/pam_namespace/pam_namespace.h
+++ b/modules/pam_namespace/pam_namespace.h
@@ -74,6 +74,14 @@
#define CLONE_NEWNS 0x00020000 /* Flag to create new namespace */
#endif
+/* mount flags for mount_private */
+#ifndef MS_REC
+#define MS_REC (1<<14)
+#endif
+#ifndef MS_PRIVATE
+#define MS_PRIVATE (1<<18)
+#endif
+
/*
* Module defines
*/
13 years
[linux-pam] Rewrite of the field parsing in pam_group and pam_time.
by Tomáš Mráz
commit 74b8ffc6d088f06e5c9fd017b5499a406dfb3fb0
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Mon Jun 6 12:22:02 2011 +0200
Rewrite of the field parsing in pam_group and pam_time.
ChangeLog | 13 ++
modules/pam_group/pam_group.c | 281 ++++++++++++++++++++---------------------
modules/pam_time/pam_time.c | 273 +++++++++++++++++++--------------------
3 files changed, 281 insertions(+), 286 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0be8f05..b0cb53a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2011-06-06 Tomas Mraz <tm(a)t8m.info>
+
+ * modules/pam_group/pam_group.c (shift_bytes): Removed.
+ (shift_buf, trim_spaces): Added new functions.
+ (read_field): Thorough rewrite of the parsing.
+ (check_account): read_field() now uses state information. No
+ extra read_field() call at the end of configuration line.
+ * modules/pam_time/pam_time.c (shift_bytes): Removed.
+ (shift_buf, trim_spaces): Added new functions.
+ (read_field): Thorough rewrite of the parsing.
+ (check_account): read_field() now uses state information. No
+ extra read_field() call at the end of configuration line.
+
2011-06-06 Nguyễn Thái Ngọc Duy <pclouds(a)gmail.com>
* po/LINGUAS: Add vietnamese.
diff --git a/modules/pam_group/pam_group.c b/modules/pam_group/pam_group.c
index 310b262..be5f20f 100644
--- a/modules/pam_group/pam_group.c
+++ b/modules/pam_group/pam_group.c
@@ -2,6 +2,7 @@
/*
* Written by Andrew Morgan <morgan(a)linux.kernel.org> 1996/7/6
+ * Field parsing rewritten by Tomas Mraz <tm(a)t8m.info>
*/
#include "config.h"
@@ -50,166 +51,156 @@ typedef enum { AND, OR } operator;
/* --- static functions for checking whether the user should be let in --- */
-static void shift_bytes(char *mem, int from, int by)
+static char *
+shift_buf(char *mem, int from)
{
- while (by-- > 0) {
- *mem = mem[from];
+ char *start = mem;
+ while ((*mem = mem[from]) != '\0')
++mem;
+ memset(mem, '\0', PAM_GROUP_BUFLEN - (mem - start));
+ return mem;
+}
+
+static void
+trim_spaces(char *buf, char *from)
+{
+ while (from > buf) {
+ --from;
+ if (*from == ' ')
+ *from = '\0';
+ else
+ break;
}
}
-/* This function should initially be called with buf = NULL. If
- * an error occurs, the file descriptor is closed. Subsequent
- * calls with a closed descriptor will cause buf to be deallocated.
- * Therefore, always check buf after calling this to see if an error
- * occurred.
- */
+#define STATE_NL 0 /* new line starting */
+#define STATE_COMMENT 1 /* inside comment */
+#define STATE_FIELD 2 /* field following */
+#define STATE_EOF 3 /* end of file or error */
+
static int
-read_field (const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
{
- /* is buf set ? */
+ char *to;
+ char *src;
+ int i;
+ char c;
+ int onspace;
+ /* is buf set ? */
if (! *buf) {
- *buf = (char *) malloc(PAM_GROUP_BUFLEN);
+ *buf = (char *) calloc(1, PAM_GROUP_BUFLEN+1);
if (! *buf) {
pam_syslog(pamh, LOG_ERR, "out of memory");
+ D(("no memory"));
+ *state = STATE_EOF;
return -1;
}
- *from = *to = 0;
+ *from = 0;
+ *state = STATE_NL;
fd = open(PAM_GROUP_CONF, O_RDONLY);
+ if (fd < 0) {
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", PAM_GROUP_CONF);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ }
}
- /* do we have a file open ? return error */
-
- if (fd < 0 && *to <= 0) {
- pam_syslog(pamh, LOG_ERR, "%s not opened", PAM_GROUP_CONF);
- memset(*buf, 0, PAM_GROUP_BUFLEN);
- _pam_drop(*buf);
- return -1;
- }
-
- /* check if there was a newline last time */
-
- if ((*to > *from) && (*to > 0)
- && ((*buf)[*from] == '\0')) { /* previous line ended */
- (*from)++;
- (*buf)[0] = '\0';
- return fd;
- }
-
- /* ready for more data: first shift the buffer's remaining data */
-
- *to -= *from;
- shift_bytes(*buf, *from, *to);
- *from = 0;
- (*buf)[*to] = '\0';
-
- while (fd >= 0 && *to < PAM_GROUP_BUFLEN) {
- int i;
-
- /* now try to fill the remainder of the buffer */
+ if (*from > 0)
+ to = shift_buf(*buf, *from);
+ else
+ to = *buf;
- i = read(fd, *to + *buf, PAM_GROUP_BUFLEN - *to);
+ while (fd != -1 && to - *buf < PAM_GROUP_BUFLEN) {
+ i = pam_modutil_read(fd, to, PAM_GROUP_BUFLEN - (to - *buf));
if (i < 0) {
pam_syslog(pamh, LOG_ERR, "error reading %s: %m", PAM_GROUP_CONF);
close(fd);
+ memset(*buf, 0, PAM_GROUP_BUFLEN);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
return -1;
} else if (!i) {
close(fd);
fd = -1; /* end of file reached */
- } else
- *to += i;
+ }
- /*
- * contract the buffer. Delete any comments, and replace all
- * multiple spaces with single commas
- */
+ to += i;
+ }
- i = 0;
-#ifdef DEBUG_DUMP
- D(("buffer=<%s>",*buf));
-#endif
- while (i < *to) {
- if ((*buf)[i] == ',') {
- int j;
-
- for (j=++i; j<*to && (*buf)[j] == ','; ++j);
- if (j!=i) {
- shift_bytes(i + (*buf), j-i, (*to) - j);
- *to -= j-i;
+ if (to == *buf) {
+ /* nothing previously in buf, nothing read */
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ }
+
+ memset(to, '\0', PAM_GROUP_BUFLEN - (to - *buf));
+
+ to = *buf;
+ onspace = 1; /* delete any leading spaces */
+
+ for (src = to; (c=*src) != '\0'; ++src) {
+ if (*state == STATE_COMMENT && c != '\n') {
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ *state = STATE_NL;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
+ return fd;
+
+ case '\t':
+ case ' ':
+ if (!onspace) {
+ onspace = 1;
+ *to++ = ' ';
}
- }
- switch ((*buf)[i]) {
- int j, c;
+ break;
+
+ case '!':
+ onspace = 1; /* ignore following spaces */
+ *to++ = '!';
+ break;
+
case '#':
- c = 0;
- for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
- if (j >= *to) {
- (*buf)[*to = ++i] = '\0';
- } else if (c == '\n') {
- shift_bytes(i + (*buf), j-i, (*to) - j);
- *to -= j-i;
- ++i;
- } else {
- pam_syslog(pamh, LOG_CRIT,
- "internal error in file %s at line %d",
- __FILE__, __LINE__);
- close(fd);
- return -1;
- }
+ *state = STATE_COMMENT;
break;
+
+ case FIELD_SEPARATOR:
+ *state = STATE_FIELD;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
+ return fd;
+
case '\\':
- if ((*buf)[i+1] == '\n') {
- shift_bytes(i + *buf, 2, *to - (i+2));
- *to -= 2;
- } else {
- ++i; /* we don't escape non-newline characters */
+ if (src[1] == '\n') {
+ ++src; /* skip it */
+ break;
}
- break;
- case '!':
- case ' ':
- case '\t':
- if ((*buf)[i] != '!')
- (*buf)[i] = ',';
- /* delete any trailing spaces */
- for (j=++i; j < *to && ( (c = (*buf)[j]) == ' '
- || c == '\t' ); ++j);
- shift_bytes(i + *buf, j-i, (*to)-j );
- *to -= j-i;
- break;
default:
- ++i;
- }
+ *to++ = c;
+ onspace = 0;
}
+ if (src > to)
+ *src = '\0'; /* clearing */
}
- (*buf)[*to] = '\0';
-
- /* now return the next field (set the from/to markers) */
- {
- int i;
-
- for (i=0; i<*to; ++i) {
- switch ((*buf)[i]) {
- case '#':
- case '\n': /* end of the line/file */
- (*buf)[i] = '\0';
- *from = i;
- return fd;
- case FIELD_SEPARATOR: /* end of the field */
- (*buf)[i] = '\0';
- *from = ++i;
- return fd;
- }
- }
- *from = i;
- (*buf)[*from] = '\0';
+ if (*state != STATE_COMMENT) {
+ *state = STATE_COMMENT;
+ pam_syslog(pamh, LOG_ERR, "field too long - ignored");
+ **buf = '\0';
+ } else {
+ *to = '\0';
+ trim_spaces(*buf, to);
}
- if (*to <= 0) {
- D(("[end of text]"));
- *buf = NULL;
- }
+ *from = 0;
return fd;
}
@@ -582,7 +573,7 @@ static int mkgrplist(pam_handle_t *pamh, char *buf, gid_t **list, int len)
static int check_account(pam_handle_t *pamh, const char *service,
const char *tty, const char *user)
{
- int from=0,to=0,fd=-1;
+ int from=0, state=STATE_NL, fd=-1;
char *buffer=NULL;
int count=0;
TIME here_and_now;
@@ -627,7 +618,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the service name field */
- fd = read_field(pamh,fd,&buffer,&from,&to);
+ fd = read_field(pamh, fd, &buffer, &from, &state);
if (!buffer || !buffer[0]) {
/* empty line .. ? */
continue;
@@ -635,15 +626,21 @@ static int check_account(pam_handle_t *pamh, const char *service,
++count;
D(("working on rule #%d",count));
+ if (state != STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: malformed rule #%d", PAM_GROUP_CONF, count);
+ continue;
+ }
+
good = logic_field(pamh,service, buffer, count, is_same);
D(("with service: %s", good ? "passes":"fails" ));
/* here we get the terminal name field */
- fd = read_field(pamh,fd,&buffer,&from,&to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no tty entry #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", PAM_GROUP_CONF, count);
continue;
}
good &= logic_field(pamh,tty, buffer, count, is_same);
@@ -651,10 +648,10 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the username field */
- fd = read_field(pamh,fd,&buffer,&from,&to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no user entry #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", PAM_GROUP_CONF, count);
continue;
}
/* If buffer starts with @, we are using netgroups */
@@ -669,20 +666,20 @@ static int check_account(pam_handle_t *pamh, const char *service,
/* here we get the time field */
- fd = read_field(pamh,fd,&buffer,&from,&to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no time entry #%d", PAM_GROUP_CONF, count);
+ "%s: malformed rule #%d", PAM_GROUP_CONF, count);
continue;
}
good &= logic_field(pamh,&here_and_now, buffer, count, check_time);
D(("with time: %s", good ? "passes":"fails" ));
- fd = read_field(pamh,fd,&buffer,&from,&to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state == STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no listed groups for rule #%d", PAM_GROUP_CONF, count);
+ "%s: poorly terminated rule #%d", PAM_GROUP_CONF, count);
continue;
}
@@ -701,14 +698,6 @@ static int check_account(pam_handle_t *pamh, const char *service,
}
}
- /* check the line is terminated correctly */
-
- fd = read_field(pamh,fd,&buffer,&from,&to);
- if (buffer && buffer[0]) {
- pam_syslog(pamh, LOG_ERR,
- "%s: poorly terminated rule #%d", PAM_GROUP_CONF, count);
- }
-
if (good > 0) {
D(("rule #%d passed, added %d groups", count, good));
} else if (good < 0) {
@@ -717,7 +706,7 @@ static int check_account(pam_handle_t *pamh, const char *service,
D(("rule #%d failed", count));
}
- } while (buffer);
+ } while (state != STATE_EOF);
/* now set the groups for the user */
diff --git a/modules/pam_time/pam_time.c b/modules/pam_time/pam_time.c
index 7e41880..dff4a6d 100644
--- a/modules/pam_time/pam_time.c
+++ b/modules/pam_time/pam_time.c
@@ -4,6 +4,7 @@
* Written by Andrew Morgan <morgan(a)linux.kernel.org> 1996/6/22
* (File syntax and much other inspiration from the shadow package
* shadow-960129)
+ * Field parsing rewritten by Tomas Mraz <tm(a)t8m.info>
*/
#include "config.h"
@@ -23,7 +24,7 @@
#include <netdb.h>
#ifdef HAVE_LIBAUDIT
-#include <libaudit.h>
+#include <libaudit.h>
#endif
#define PAM_TIME_BUFLEN 1000
@@ -79,163 +80,157 @@ _pam_parse (const pam_handle_t *pamh, int argc, const char **argv)
/* --- static functions for checking whether the user should be let in --- */
-static void
-shift_bytes(char *mem, int from, int by)
+static char *
+shift_buf(char *mem, int from)
{
- while (by-- > 0) {
- *mem = mem[from];
+ char *start = mem;
+ while ((*mem = mem[from]) != '\0')
++mem;
+ memset(mem, '\0', PAM_TIME_BUFLEN - (mem - start));
+ return mem;
+}
+
+static void
+trim_spaces(char *buf, char *from)
+{
+ while (from > buf) {
+ --from;
+ if (*from == ' ')
+ *from = '\0';
+ else
+ break;
}
}
+#define STATE_NL 0 /* new line starting */
+#define STATE_COMMENT 1 /* inside comment */
+#define STATE_FIELD 2 /* field following */
+#define STATE_EOF 3 /* end of file or error */
+
static int
-read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *to)
+read_field(const pam_handle_t *pamh, int fd, char **buf, int *from, int *state)
{
- /* is buf set ? */
+ char *to;
+ char *src;
+ int i;
+ char c;
+ int onspace;
+ /* is buf set ? */
if (! *buf) {
- *buf = (char *) malloc(PAM_TIME_BUFLEN);
+ *buf = (char *) calloc(1, PAM_TIME_BUFLEN+1);
if (! *buf) {
pam_syslog(pamh, LOG_ERR, "out of memory");
D(("no memory"));
+ *state = STATE_EOF;
return -1;
}
- *from = *to = 0;
+ *from = 0;
+ *state = STATE_NL;
fd = open(PAM_TIME_CONF, O_RDONLY);
+ if (fd < 0) {
+ pam_syslog(pamh, LOG_ERR, "error opening %s: %m", PAM_TIME_CONF);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
+ }
}
+
- /* do we have a file open ? return error */
-
- if (fd < 0 && *to <= 0) {
- pam_syslog(pamh, LOG_ERR, "error opening %s: %m", PAM_TIME_CONF);
- memset(*buf, 0, PAM_TIME_BUFLEN);
- _pam_drop(*buf);
- return -1;
- }
-
- /* check if there was a newline last time */
-
- if ((*to > *from) && (*to > 0)
- && ((*buf)[*from] == '\0')) { /* previous line ended */
- (*from)++;
- (*buf)[0] = '\0';
- return fd;
- }
-
- /* ready for more data: first shift the buffer's remaining data */
-
- *to -= *from;
- shift_bytes(*buf, *from, *to);
- *from = 0;
- (*buf)[*to] = '\0';
-
- while (fd >= 0 && *to < PAM_TIME_BUFLEN) {
- int i;
-
- /* now try to fill the remainder of the buffer */
+ if (*from > 0)
+ to = shift_buf(*buf, *from);
+ else
+ to = *buf;
- i = read(fd, *to + *buf, PAM_TIME_BUFLEN - *to);
+ while (fd != -1 && to - *buf < PAM_TIME_BUFLEN) {
+ i = pam_modutil_read(fd, to, PAM_TIME_BUFLEN - (to - *buf));
if (i < 0) {
pam_syslog(pamh, LOG_ERR, "error reading %s: %m", PAM_TIME_CONF);
close(fd);
+ memset(*buf, 0, PAM_TIME_BUFLEN);
+ _pam_drop(*buf);
+ *state = STATE_EOF;
return -1;
} else if (!i) {
close(fd);
fd = -1; /* end of file reached */
- } else
- *to += i;
+ }
- /*
- * contract the buffer. Delete any comments, and replace all
- * multiple spaces with single commas
- */
+ to += i;
+ }
- i = 0;
-#ifdef DEBUG_DUMP
- D(("buffer=<%s>",*buf));
-#endif
- while (i < *to) {
- if ((*buf)[i] == ',') {
- int j;
-
- for (j=++i; j<*to && (*buf)[j] == ','; ++j);
- if (j!=i) {
- shift_bytes(i + (*buf), j-i, (*to) - j);
- *to -= j-i;
- }
- }
- switch ((*buf)[i]) {
- int j,c;
- case '#':
- c = 0;
- for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
- if (j >= *to) {
- (*buf)[*to = ++i] = '\0';
- } else if (c == '\n') {
- shift_bytes(i + (*buf), j-i, (*to) - j);
- *to -= j-i;
- ++i;
- } else {
- pam_syslog(pamh, LOG_CRIT,
- "internal error in file %s at line %d",
- __FILE__, __LINE__);
- close(fd);
- return -1;
- }
- break;
- case '\\':
- if ((*buf)[i+1] == '\n') {
- shift_bytes(i + *buf, 2, *to - (i+2));
- *to -= 2;
- } else {
- ++i; /* we don't escape non-newline characters */
- }
- break;
- case '!':
- case ' ':
- case '\t':
- if ((*buf)[i] != '!')
- (*buf)[i] = ',';
- /* delete any trailing spaces */
- for (j=++i; j < *to && ( (c = (*buf)[j]) == ' '
- || c == '\t' ); ++j);
- shift_bytes(i + *buf, j-i, (*to)-j );
- *to -= j-i;
- break;
- default:
- ++i;
- }
- }
+ if (to == *buf) {
+ /* nothing previously in buf, nothing read */
+ _pam_drop(*buf);
+ *state = STATE_EOF;
+ return -1;
}
- (*buf)[*to] = '\0';
+ memset(to, '\0', PAM_TIME_BUFLEN - (to - *buf));
- /* now return the next field (set the from/to markers) */
- {
- int i;
+ to = *buf;
+ onspace = 1; /* delete any leading spaces */
+
+ for (src = to; (c=*src) != '\0'; ++src) {
+ if (*state == STATE_COMMENT && c != '\n') {
+ continue;
+ }
+
+ switch (c) {
+ case '\n':
+ *state = STATE_NL;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
+ return fd;
+
+ case '\t':
+ case ' ':
+ if (!onspace) {
+ onspace = 1;
+ *to++ = ' ';
+ }
+ break;
+
+ case '!':
+ onspace = 1; /* ignore following spaces */
+ *to++ = '!';
+ break;
- for (i=0; i<*to; ++i) {
- switch ((*buf)[i]) {
case '#':
- case '\n': /* end of the line/file */
- (*buf)[i] = '\0';
- *from = i;
+ *state = STATE_COMMENT;
+ break;
+
+ case FIELD_SEPARATOR:
+ *state = STATE_FIELD;
+ *to = '\0';
+ *from = (src - *buf) + 1;
+ trim_spaces(*buf, to);
return fd;
- case FIELD_SEPARATOR: /* end of the field */
- (*buf)[i] = '\0';
- *from = ++i;
- return fd;
- }
+
+ case '\\':
+ if (src[1] == '\n') {
+ ++src; /* skip it */
+ break;
+ }
+ default:
+ *to++ = c;
+ onspace = 0;
}
- *from = i;
- (*buf)[*from] = '\0';
+ if (src > to)
+ *src = '\0'; /* clearing */
}
- if (*to <= 0) {
- D(("[end of text]"));
- *buf = NULL;
+ if (*state != STATE_COMMENT) {
+ *state = STATE_COMMENT;
+ pam_syslog(pamh, LOG_ERR, "field too long - ignored");
+ **buf = '\0';
+ } else {
+ *to = '\0';
+ trim_spaces(*buf, to);
}
+ *from = 0;
return fd;
}
@@ -511,7 +506,7 @@ static int
check_account(pam_handle_t *pamh, const char *service,
const char *tty, const char *user)
{
- int from=0,to=0,fd=-1;
+ int from=0, state=STATE_NL, fd=-1;
char *buffer=NULL;
int count=0;
TIME here_and_now;
@@ -523,23 +518,28 @@ check_account(pam_handle_t *pamh, const char *service,
/* here we get the service name field */
- fd = read_field(pamh, fd, &buffer, &from, &to);
-
+ fd = read_field(pamh, fd, &buffer, &from, &state);
if (!buffer || !buffer[0]) {
/* empty line .. ? */
continue;
}
++count;
+ if (state != STATE_FIELD) {
+ pam_syslog(pamh, LOG_ERR,
+ "%s: malformed rule #%d", PAM_TIME_CONF, count);
+ continue;
+ }
+
good = logic_field(pamh, service, buffer, count, is_same);
D(("with service: %s", good ? "passes":"fails" ));
/* here we get the terminal name field */
- fd = read_field(pamh, fd, &buffer, &from, &to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no tty entry #%d", PAM_TIME_CONF, count);
+ "%s: malformed rule #%d", PAM_TIME_CONF, count);
continue;
}
good &= logic_field(pamh, tty, buffer, count, is_same);
@@ -547,10 +547,10 @@ check_account(pam_handle_t *pamh, const char *service,
/* here we get the username field */
- fd = read_field(pamh, fd, &buffer, &from, &to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state != STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no user entry #%d", PAM_TIME_CONF, count);
+ "%s: malformed rule #%d", PAM_TIME_CONF, count);
continue;
}
/* If buffer starts with @, we are using netgroups */
@@ -562,23 +562,16 @@ check_account(pam_handle_t *pamh, const char *service,
/* here we get the time field */
- fd = read_field(pamh, fd, &buffer, &from, &to);
- if (!buffer || !buffer[0]) {
+ fd = read_field(pamh, fd, &buffer, &from, &state);
+ if (state == STATE_FIELD) {
pam_syslog(pamh, LOG_ERR,
- "%s: no time entry #%d", PAM_TIME_CONF, count);
+ "%s: poorly terminated rule #%d", PAM_TIME_CONF, count);
continue;
}
intime = logic_field(pamh, &here_and_now, buffer, count, check_time);
D(("with time: %s", intime ? "passes":"fails" ));
- fd = read_field(pamh, fd, &buffer, &from, &to);
- if (buffer && buffer[0]) {
- pam_syslog(pamh, LOG_ERR,
- "%s: poorly terminated rule #%d", PAM_TIME_CONF, count);
- continue;
- }
-
if (good && !intime) {
/*
* for security parse whole file.. also need to ensure
@@ -588,7 +581,7 @@ check_account(pam_handle_t *pamh, const char *service,
} else {
D(("rule passed"));
}
- } while (buffer);
+ } while (state != STATE_EOF);
return retval;
}
13 years
[linux-pam] Vietnamese translation added.
by Tomáš Mráz
commit 83814bc0e43f4f7606efbf30b1df39be287a0aa2
Author: Tomas Mraz <tmraz(a)fedoraproject.org>
Date: Mon Jun 6 08:23:42 2011 +0200
Vietnamese translation added.
ChangeLog | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index a7c485c..0be8f05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-06 Nguyễn Thái Ngọc Duy <pclouds(a)gmail.com>
+
+ * po/LINGUAS: Add vietnamese.
+ * po/vi.po: Add vietnamese translation.
+
2011-06-02 Tomas Mraz <tm(a)t8m.info>
* modules/pam_namespace/pam_namespace.c (protect_dir): Add parameter
13 years
[linux-pam] po: add Vietnamese translation
by Tomáš Mráz
commit 6b2631afddb131d2f4b3f0caf8b46c936eae3407
Author: Nguyễn Thái Ngọc Duy <pclouds(a)gmail.com>
Date: Sun Jun 5 14:27:41 2011 +0700
po: add Vietnamese translation
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds(a)gmail.com>
po/LINGUAS | 1 +
po/vi.po | 578 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 579 insertions(+), 0 deletions(-)
---
diff --git a/po/LINGUAS b/po/LINGUAS
index 028bd46..9d5f6a8 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -38,6 +38,7 @@ ta
te
tr
uk
+vi
zh_CN
zh_TW
zu
diff --git a/po/vi.po b/po/vi.po
new file mode 100644
index 0000000..da13fbb
--- /dev/null
+++ b/po/vi.po
@@ -0,0 +1,578 @@
+# Vietnamese translation for pam
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the pam package.
+# Ubuntu Vietname translators <ubuntu-l10n-vi(a)lists.launchpad.net>, 2009-2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: pam\n"
+"Report-Msgid-Bugs-To: http://sourceforge.net/projects/pam\n"
+"POT-Creation-Date: 2010-10-20 15:15+0200\n"
+"PO-Revision-Date: 2011-06-04 17:58+0700\n"
+"Last-Translator: Lê Trường An <truongan(a)linuxmail.org>\n"
+"Language-Team: Vietnamese <du-an-most(a)lists.hanoilug.org>\n"
+"Language: vi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"X-Launchpad-Export-Date: 2011-06-04 10:52+0000\n"
+"X-Generator: Launchpad (build 13144)\n"
+
+#: libpam_misc/misc_conv.c:33
+msgid "...Time is running out...\n"
+msgstr "...Thời gian đang dần hết...\n"
+
+#: libpam_misc/misc_conv.c:34
+msgid "...Sorry, your time is up!\n"
+msgstr "...Xin lỗi, đã hết thời gian!\n"
+
+#: libpam_misc/misc_conv.c:342
+#, c-format
+msgid "erroneous conversation (%d)\n"
+msgstr "hội thoại sai (%d)\n"
+
+#: libpam/pam_get_authtok.c:39 modules/pam_exec/pam_exec.c:142
+#: modules/pam_unix/pam_unix_auth.c:157 modules/pam_userdb/pam_userdb.c:64
+msgid "Password: "
+msgstr "Mật khẩu : "
+
+#: libpam/pam_get_authtok.c:41 modules/pam_cracklib/pam_cracklib.c:66
+#, c-format
+msgid "New %s%spassword: "
+msgstr "Mật khẩu %s%s mới: "
+
+#: libpam/pam_get_authtok.c:43 modules/pam_cracklib/pam_cracklib.c:68
+#, c-format
+msgid "Retype new %s%spassword: "
+msgstr "Nhập lại mật khẩu %s%s mới: "
+
+#: libpam/pam_get_authtok.c:44 modules/pam_cracklib/pam_cracklib.c:69
+msgid "Sorry, passwords do not match."
+msgstr "Xin lỗi, mật khẩu không khớp."
+
+#: libpam/pam_get_authtok.c:133 libpam/pam_get_authtok.c:209
+#, c-format
+msgid "Retype %s"
+msgstr "Nhập lại %s"
+
+#: libpam/pam_get_authtok.c:153 libpam/pam_get_authtok.c:222
+msgid "Password change aborted."
+msgstr "Hủy bỏ việc thay đổi mật khẩu."
+
+#: libpam/pam_item.c:310
+msgid "login:"
+msgstr "Đăng nhập:"
+
+#: libpam/pam_strerror.c:40
+msgid "Success"
+msgstr "Thành công"
+
+#: libpam/pam_strerror.c:42
+msgid "Critical error - immediate abort"
+msgstr "Lỗi nghiêm trọng - hủy bỏ ngay"
+
+#: libpam/pam_strerror.c:44
+msgid "Failed to load module"
+msgstr "Không thể nạp mô-đun"
+
+#: libpam/pam_strerror.c:46
+msgid "Symbol not found"
+msgstr "Không tìm thấy biểu tượng"
+
+#: libpam/pam_strerror.c:48
+msgid "Error in service module"
+msgstr "Lỗi trong mô-đun dịch vụ"
+
+#: libpam/pam_strerror.c:50
+msgid "System error"
+msgstr "Lỗi hệ thống"
+
+#: libpam/pam_strerror.c:52
+msgid "Memory buffer error"
+msgstr "Lỗi bộ nhớ đệm"
+
+#: libpam/pam_strerror.c:54
+msgid "Permission denied"
+msgstr "Không có đủ quyền thực hiện"
+
+#: libpam/pam_strerror.c:56
+msgid "Authentication failure"
+msgstr "Xác thực thất bại"
+
+#: libpam/pam_strerror.c:58
+msgid "Insufficient credentials to access authentication data"
+msgstr "Không đủ quyền uỷ nhiệm để truy cập dữ liệu xác thực"
+
+#: libpam/pam_strerror.c:60
+msgid "Authentication service cannot retrieve authentication info"
+msgstr "Dịch vụ chứng thực không thể lấy các thông tin xác thực"
+
+#: libpam/pam_strerror.c:62
+msgid "User not known to the underlying authentication module"
+msgstr "Người dùng chưa biết đến mô-đun xác thực tiềm ẩn"
+
+#: libpam/pam_strerror.c:64
+msgid "Have exhausted maximum number of retries for service"
+msgstr "Đã hết số lần thử lại tối đa cho dịch vụ"
+
+#: libpam/pam_strerror.c:66
+msgid "Authentication token is no longer valid; new one required"
+msgstr "Dấu hiệu xác thực không còn hiệu lực; yêu cầu dấu hiệu xác thực mới"
+
+#: libpam/pam_strerror.c:68
+msgid "User account has expired"
+msgstr "Tài khoản người dùng đã hết hiệu lực"
+
+#: libpam/pam_strerror.c:70
+msgid "Cannot make/remove an entry for the specified session"
+msgstr "Không thể thực hiện hoặc loại bỏ một mục nhập cho phiên định"
+
+#: libpam/pam_strerror.c:72
+msgid "Authentication service cannot retrieve user credentials"
+msgstr "Dịch vụ chứng thực không thể lấy các chứng chỉ người dùng"
+
+#: libpam/pam_strerror.c:74
+msgid "User credentials expired"
+msgstr "Hết hạn ủy nhiệm người dùng"
+
+#: libpam/pam_strerror.c:76
+msgid "Failure setting user credentials"
+msgstr "Cài đặt ủy nhiệm người dùng thất bại"
+
+#: libpam/pam_strerror.c:78
+msgid "No module specific data is present"
+msgstr "Hiện tại không có mô-đun dữ liệu"
+
+#: libpam/pam_strerror.c:80
+msgid "Bad item passed to pam_*_item()"
+msgstr "Tình trạng hàng được thông qua để pam_ * _item ()"
+
+#: libpam/pam_strerror.c:82
+msgid "Conversation error"
+msgstr "Lỗi giao tiếp"
+
+#: libpam/pam_strerror.c:84
+msgid "Authentication token manipulation error"
+msgstr "Thao tác xác thực token lỗi"
+
+#: libpam/pam_strerror.c:86
+msgid "Authentication information cannot be recovered"
+msgstr "Xác thực thông tin không thể được phục hồi"
+
+#: libpam/pam_strerror.c:88
+msgid "Authentication token lock busy"
+msgstr "authentication token lock busy"
+
+#: libpam/pam_strerror.c:90
+msgid "Authentication token aging disabled"
+msgstr "xác thực token già tàn tật"
+
+#: libpam/pam_strerror.c:92
+msgid "Failed preliminary check by password service"
+msgstr "Không thành công sơ bộ kiểm tra bằng mật khẩu dịch vụ"
+
+#: libpam/pam_strerror.c:94
+msgid "The return value should be ignored by PAM dispatch"
+msgstr "Giá trị trả về phải được bỏ qua bởi PAM công văn"
+
+#: libpam/pam_strerror.c:96
+msgid "Module is unknown"
+msgstr "chưa biết mô-đun"
+
+#: libpam/pam_strerror.c:98
+msgid "Authentication token expired"
+msgstr "Hết hạn xác thực"
+
+#: libpam/pam_strerror.c:100
+msgid "Conversation is waiting for event"
+msgstr "Giao tiếp đang chờ kết quả"
+
+#: libpam/pam_strerror.c:102
+msgid "Application needs to call libpam again"
+msgstr "Ứng dụng cần gọi libpam lần nữa"
+
+#: libpam/pam_strerror.c:105
+msgid "Unknown PAM error"
+msgstr "Không biết lỗi PAM"
+
+#: modules/pam_cracklib/pam_cracklib.c:490
+msgid "is the same as the old one"
+msgstr "là giống như cũ"
+
+#: modules/pam_cracklib/pam_cracklib.c:504
+msgid "is a palindrome"
+msgstr "là một xâu palindrome"
+
+#: modules/pam_cracklib/pam_cracklib.c:507
+msgid "case changes only"
+msgstr "chỉ thay đổi chữ thường/hoa"
+
+#: modules/pam_cracklib/pam_cracklib.c:510
+msgid "is too similar to the old one"
+msgstr "quá giống cái cũ"
+
+#: modules/pam_cracklib/pam_cracklib.c:513
+msgid "is too simple"
+msgstr "quá đơn giản"
+
+#: modules/pam_cracklib/pam_cracklib.c:516
+msgid "is rotated"
+msgstr "được sử dụng lại"
+
+#: modules/pam_cracklib/pam_cracklib.c:519
+msgid "not enough character classes"
+msgstr "không đủ các lớp nhân vật"
+
+#: modules/pam_cracklib/pam_cracklib.c:522
+msgid "contains too many same characters consecutively"
+msgstr "chứa quá nhiều kí tự giống nhau liên tiếp"
+
+#: modules/pam_cracklib/pam_cracklib.c:525
+msgid "contains the user name in some form"
+msgstr "chứa tên user trong một số biểu mẫu"
+
+#: modules/pam_cracklib/pam_cracklib.c:555
+#: modules/pam_unix/pam_unix_passwd.c:476
+msgid "No password supplied"
+msgstr "Không có mật khẩu được cung cấp"
+
+#: modules/pam_cracklib/pam_cracklib.c:555
+#: modules/pam_unix/pam_unix_passwd.c:476
+msgid "Password unchanged"
+msgstr "Chưa thay đổi mật khẩu"
+
+#: modules/pam_cracklib/pam_cracklib.c:575
+#: modules/pam_cracklib/pam_cracklib.c:658
+#, c-format
+msgid "BAD PASSWORD: %s"
+msgstr "Mật khẩu không an toàn: %s"
+
+#: modules/pam_exec/pam_exec.c:215
+#, c-format
+msgid "%s failed: exit code %d"
+msgstr "%s thất bại: lối ra mã %d"
+
+#: modules/pam_exec/pam_exec.c:224
+#, c-format
+msgid "%s failed: caught signal %d%s"
+msgstr "%s thất bại: bắt tín hiệu %d%s"
+
+#: modules/pam_exec/pam_exec.c:233
+#, c-format
+msgid "%s failed: unknown status 0x%x"
+msgstr "%s thất bại: không rõ tình trạng 0x%x"
+
+#. TRANSLATORS: "strftime options for date of last login"
+#: modules/pam_lastlog/pam_lastlog.c:201 modules/pam_lastlog/pam_lastlog.c:429
+msgid " %a %b %e %H:%M:%S %Z %Y"
+msgstr " %a %b %e %H:%M:%S %Z %Y"
+
+#. TRANSLATORS: " from <host>"
+#: modules/pam_lastlog/pam_lastlog.c:210 modules/pam_lastlog/pam_lastlog.c:438
+#, c-format
+msgid " from %.*s"
+msgstr " từ %.*s"
+
+#. TRANSLATORS: " on <terminal>"
+#: modules/pam_lastlog/pam_lastlog.c:222 modules/pam_lastlog/pam_lastlog.c:450
+#, c-format
+msgid " on %.*s"
+msgstr " trên %.*s"
+
+#. TRANSLATORS: "Last login: <date> from <host> on <terminal>"
+#: modules/pam_lastlog/pam_lastlog.c:232
+#, c-format
+msgid "Last login:%s%s%s"
+msgstr "Lần đăng nhập:%s%s%s"
+
+#: modules/pam_lastlog/pam_lastlog.c:238
+msgid "Welcome to your new account!"
+msgstr "Chào mừng bạn đến tài khoản mới của bạn!"
+
+#. TRANSLATORS: "Last failed login: <date> from <host> on <terminal>"
+#: modules/pam_lastlog/pam_lastlog.c:460
+#, c-format
+msgid "Last failed login:%s%s%s"
+msgstr "Lần đăng nhập thất bại trước:%s%s%s"
+
+#: modules/pam_lastlog/pam_lastlog.c:469 modules/pam_lastlog/pam_lastlog.c:476
+#, c-format
+msgid "There was %d failed login attempt since the last successful login."
+msgid_plural ""
+"There were %d failed login attempts since the last successful login."
+msgstr[0] ""
+"Đã có %d lần đăng nhập thất bại kể từ lần đăng nhập thành công trước đó."
+
+#. TRANSLATORS: only used if dngettext is not supported
+#: modules/pam_lastlog/pam_lastlog.c:481
+#, c-format
+msgid "There were %d failed login attempts since the last successful login."
+msgstr ""
+"Có %d lần đăng nhập không thành công kể từ lần đăng nhập thành công trước."
+
+#: modules/pam_limits/pam_limits.c:786
+#, c-format
+msgid "Too many logins for '%s'."
+msgstr "Quá nhiều lần đăng nhập cho '%s'."
+
+#: modules/pam_mail/pam_mail.c:297
+msgid "No mail."
+msgstr "Không có thư."
+
+#: modules/pam_mail/pam_mail.c:300
+msgid "You have new mail."
+msgstr "Bạn có thư mới."
+
+#: modules/pam_mail/pam_mail.c:303
+msgid "You have old mail."
+msgstr "Bạn có thư cũ."
+
+#: modules/pam_mail/pam_mail.c:307
+msgid "You have mail."
+msgstr "Bạn có thư."
+
+#: modules/pam_mail/pam_mail.c:314
+#, c-format
+msgid "You have no mail in folder %s."
+msgstr "Bạn không có thư trong thư mục %s."
+
+#: modules/pam_mail/pam_mail.c:318
+#, c-format
+msgid "You have new mail in folder %s."
+msgstr "Bạn có thư mới trong thư mục %s."
+
+#: modules/pam_mail/pam_mail.c:322
+#, c-format
+msgid "You have old mail in folder %s."
+msgstr "Bạn có thư cũ trong thư mục %s."
+
+#: modules/pam_mail/pam_mail.c:327
+#, c-format
+msgid "You have mail in folder %s."
+msgstr "Bạn có thư trong thư mục %s."
+
+#: modules/pam_mkhomedir/pam_mkhomedir.c:113
+#, c-format
+msgid "Creating directory '%s'."
+msgstr "Tạo thư mục '%s'."
+
+#: modules/pam_mkhomedir/pam_mkhomedir.c:183
+#, c-format
+msgid "Unable to create and initialize directory '%s'."
+msgstr "Không thể khởi tạo thư mục '%s'."
+
+#: modules/pam_pwhistory/pam_pwhistory.c:218
+#: modules/pam_unix/pam_unix_passwd.c:497
+msgid "Password has been already used. Choose another."
+msgstr "Mật khẩu đã được dùng. Hãy chọn mật khẩu khác."
+
+#: modules/pam_selinux/pam_selinux.c:172
+msgid "Would you like to enter a security context? [N] "
+msgstr "Bạn có muốn nhập một bối cảnh an ninh? [N] "
+
+#: modules/pam_selinux/pam_selinux.c:191 modules/pam_selinux/pam_selinux.c:282
+msgid "role:"
+msgstr "Vai trò:"
+
+#: modules/pam_selinux/pam_selinux.c:204 modules/pam_selinux/pam_selinux.c:316
+msgid "level:"
+msgstr "trình độ:"
+
+#: modules/pam_selinux/pam_selinux.c:219 modules/pam_selinux/pam_selinux.c:349
+msgid "Not a valid security context"
+msgstr "Không phải là một bối cảnh an ninh hợp lệ"
+
+#: modules/pam_selinux/pam_selinux.c:265
+#, c-format
+msgid "Default Security Context %s\n"
+msgstr "Bối cảnh an ninh mặc định %s\n"
+
+#: modules/pam_selinux/pam_selinux.c:269
+msgid "Would you like to enter a different role or level?"
+msgstr "Bạn có muốn nhập một vai trò khác nhau hoặc cấp?"
+
+#: modules/pam_selinux/pam_selinux.c:285
+#, c-format
+msgid "No default type for role %s\n"
+msgstr "Không có loại mặc định cho vai trò %s\n"
+
+#: modules/pam_selinux/pam_selinux.c:667
+#, c-format
+msgid "Unable to get valid context for %s"
+msgstr "Không thể có được bối cảnh hợp lệ cho %s"
+
+#: modules/pam_selinux/pam_selinux.c:718
+#, c-format
+msgid "Security Context %s Assigned"
+msgstr "Bối cảnh an ninh %s Giao"
+
+#: modules/pam_selinux/pam_selinux.c:739
+#, c-format
+msgid "Key Creation Context %s Assigned"
+msgstr "Sáng tạo Context phím %s Giao"
+
+#: modules/pam_selinux/pam_selinux_check.c:99
+#, c-format
+msgid "failed to initialize PAM\n"
+msgstr "không thể khởi tạo PAM\n"
+
+#: modules/pam_selinux/pam_selinux_check.c:105
+#, c-format
+msgid "failed to pam_set_item()\n"
+msgstr "không pam_set_item ()\n"
+
+#: modules/pam_selinux/pam_selinux_check.c:133
+#, c-format
+msgid "login: failure forking: %m"
+msgstr "đăng nhập: thất bại forking: %m"
+
+#: modules/pam_stress/pam_stress.c:475
+#, c-format
+msgid "Changing STRESS password for %s."
+msgstr "Thay đổi mật khẩu căng thẳng cho %s."
+
+#: modules/pam_stress/pam_stress.c:489
+msgid "Enter new STRESS password: "
+msgstr "Nhập mật khẩu căng thẳng mới: "
+
+#: modules/pam_stress/pam_stress.c:492
+msgid "Retype new STRESS password: "
+msgstr "Nhập lại mật khẩu mới căng thẳng: "
+
+#: modules/pam_stress/pam_stress.c:521
+msgid "Verification mis-typed; password unchanged"
+msgstr "Mã xác nhận mis-đánh máy; mật khẩu không thay đổi"
+
+#: modules/pam_tally/pam_tally.c:541 modules/pam_tally2/pam_tally2.c:596
+#, c-format
+msgid "Account temporary locked (%ld seconds left)"
+msgstr "Tài khoản tạm thời bị khóa (%ld giây còn lại)"
+
+#: modules/pam_tally/pam_tally.c:566 modules/pam_tally2/pam_tally2.c:575
+#, c-format
+msgid "Account locked due to %u failed logins"
+msgstr "Tài khoản bị khóa do đăng nhập %u không thành công"
+
+#: modules/pam_tally/pam_tally.c:777 modules/pam_tally2/pam_tally2.c:884
+msgid "Authentication error"
+msgstr "Xác thực lỗi"
+
+#: modules/pam_tally/pam_tally.c:778 modules/pam_tally2/pam_tally2.c:885
+msgid "Service error"
+msgstr "Lỗi dịch vụ"
+
+#: modules/pam_tally/pam_tally.c:779 modules/pam_tally2/pam_tally2.c:886
+msgid "Unknown user"
+msgstr "Người dùng không rõ"
+
+#: modules/pam_tally/pam_tally.c:780 modules/pam_tally2/pam_tally2.c:887
+msgid "Unknown error"
+msgstr "Lỗi không rõ"
+
+#: modules/pam_tally/pam_tally.c:796 modules/pam_tally2/pam_tally2.c:906
+#, c-format
+msgid "%s: Bad number given to --reset=\n"
+msgstr "%s: Xấu số cho --cài lại=\n"
+
+#: modules/pam_tally/pam_tally.c:800 modules/pam_tally2/pam_tally2.c:910
+#, c-format
+msgid "%s: Unrecognised option %s\n"
+msgstr "%s: Được thừa nhận lựa chọn%s\n"
+
+#: modules/pam_tally/pam_tally.c:812
+#, c-format
+msgid ""
+"%s: [--file rooted-filename] [--user username] [--reset[=n]] [--quiet]\n"
+msgstr ""
+"%s: [- tập bắt rễ-filename] [- người sử dụng tên người dùng] [- đặt lại [= "
+"n]] [- yên tĩnh]\n"
+
+#: modules/pam_tally/pam_tally.c:886 modules/pam_tally2/pam_tally2.c:1036
+#, c-format
+msgid "%s: Can't reset all users to non-zero\n"
+msgstr "%s: Không thể thiết lập lại tất cả các người dùng khác không\n"
+
+#: modules/pam_tally2/pam_tally2.c:937
+#, c-format
+msgid "Login Failures Latest failure From\n"
+msgstr "Đang nhập Thất bại Thất bại cuốie Từ \n"
+
+#: modules/pam_tally2/pam_tally2.c:953
+#, c-format
+msgid ""
+"%s: [-f rooted-filename] [--file rooted-filename]\n"
+" [-u username] [--user username]\n"
+" [-r] [--reset[=n]] [--quiet]\n"
+msgstr ""
+"%s: [-f rooted-filename] [--file rooted-filename]\n"
+" [-u username] [--user username]\n"
+" [-r] [--reset[=n]] [--quiet]\n"
+
+#: modules/pam_timestamp/pam_timestamp.c:345
+#, c-format
+msgid "Access granted (last access was %ld seconds ago)."
+msgstr "Được phép truy cập (lần truy cập trước %ld giây trước)"
+
+#: modules/pam_unix/pam_unix_acct.c:236 modules/pam_unix/pam_unix_acct.c:258
+msgid "Your account has expired; please contact your system administrator"
+msgstr ""
+"Tài khoản của bạn đã hết hạn dùng: hãy liên lạc với nhà quản trị hệ thống"
+
+#: modules/pam_unix/pam_unix_acct.c:244
+msgid "You are required to change your password immediately (root enforced)"
+msgstr "Bạn phải thay đổi ngay mật khẩu (người chủ ép buộc)"
+
+#: modules/pam_unix/pam_unix_acct.c:250
+msgid "You are required to change your password immediately (password aged)"
+msgstr "Bạn phải thay đổi ngay mật khẩu (mật khẩu quá cũ)"
+
+#: modules/pam_unix/pam_unix_acct.c:271 modules/pam_unix/pam_unix_acct.c:278
+#, c-format
+msgid "Warning: your password will expire in %d day"
+msgid_plural "Warning: your password will expire in %d days"
+msgstr[0] "Cảnh báo: mật khẩu của bạn sẽ hết hạn trong %d ngày"
+
+#. TRANSLATORS: only used if dngettext is not supported
+#: modules/pam_unix/pam_unix_acct.c:283
+#, c-format
+msgid "Warning: your password will expire in %d days"
+msgstr "Cảnh báo: mật khẩu của bạn sẽ hết hạn trong %d ngày"
+
+#: modules/pam_unix/pam_unix_passwd.c:385
+msgid "NIS password could not be changed."
+msgstr "NIS mật khẩu không thể được thay đổi."
+
+#: modules/pam_unix/pam_unix_passwd.c:493
+msgid "You must choose a longer password"
+msgstr "Bạn phải chọn mật khẩu dài hơn"
+
+#: modules/pam_unix/pam_unix_passwd.c:600
+#, c-format
+msgid "Changing password for %s."
+msgstr "Thay đổi mật khẩu cho %s."
+
+#: modules/pam_unix/pam_unix_passwd.c:611
+msgid "(current) UNIX password: "
+msgstr "hiện hành UNIX mật khẩu: "
+
+#: modules/pam_unix/pam_unix_passwd.c:646
+msgid "You must wait longer to change your password"
+msgstr "Bạn phải đợi thêm nữa, để thay đổi mật khẩu"
+
+#: modules/pam_unix/pam_unix_passwd.c:706
+msgid "Enter new UNIX password: "
+msgstr "Nhập mật khẩu UNIX mới: "
+
+#: modules/pam_unix/pam_unix_passwd.c:707
+msgid "Retype new UNIX password: "
+msgstr "Nhập lại mật khẩu UNIX mới: "
+
+#~ msgid "has been already used"
+#~ msgstr "đã được đã được sử dụng"
+
+#~ msgid "Unable to create directory %s: %m"
+#~ msgstr "Không thể tạo thư mục %s: %m"
+
+#~ msgid "Requested MLS level not in permitted range"
+#~ msgstr "Số MLS yêu cầu cấp không được cho phép trong phạm vi"
13 years