changeset e3908de967e4 in /srv/hg/libpwquality
details:
http://hg.fedorahosted.org/hg/srv/hg/libpwquality?cmd=changeset;node=e390...
summary: Updated Czech translation.
changeset d84f87223ebb in /srv/hg/libpwquality
details:
http://hg.fedorahosted.org/hg/srv/hg/libpwquality?cmd=changeset;node=d84f...
summary: Add checks for words from passwd GECOS field and for maximum consecutive
characters of same class.
diffstat:
doc/man/pam_pwquality.8 | 16 ++++++++
doc/man/pwquality.conf.5 | 14 +++++++
po/cs.po | 6 +--
src/check.c | 94 ++++++++++++++++++++++++++++++++++++++++++++---
src/error.c | 8 ++++
src/pwqprivate.h | 4 ++
src/pwquality.conf | 11 +++++-
src/pwquality.h | 4 ++
src/settings.c | 17 ++++++++-
9 files changed, 162 insertions(+), 12 deletions(-)
diffs (358 lines):
diff -r bc63c08e8a10 -r d84f87223ebb doc/man/pam_pwquality.8
--- a/doc/man/pam_pwquality.8 Fri Nov 11 12:28:16 2011 +0100
+++ b/doc/man/pam_pwquality.8 Tue Dec 06 21:07:55 2011 +0100
@@ -217,6 +217,22 @@
The default is 0 which means that this check is disabled\&.
.RE
.PP
+\fBmaxclassrepeat=\fR\fB\fIN\fR\fR
+.RS 4
+Reject passwords which contain more than N consecutive characters of the
+same class\&.
+The default is 0 which means that this check is disabled\&.
+.RE
+.PP
+\fBgecoscheck=\fR\fB\fIN\fR\fR
+.RS 4
+If nonzero, check whether the individual words longer than 3 characters
+from the
+\fBpasswd GECOS\fR
+field of the user are contained in the new password\&.
+The default is 0 which means that this check is disabled\&.
+.RE
+.PP
\fBuse_authtok\fR
.RS 4
This argument is used to
diff -r bc63c08e8a10 -r d84f87223ebb doc/man/pwquality.conf.5
--- a/doc/man/pwquality.conf.5 Fri Nov 11 12:28:16 2011 +0100
+++ b/doc/man/pwquality.conf.5 Tue Dec 06 21:07:55 2011 +0100
@@ -78,6 +78,20 @@
The check is disabled if the value is 0. (default 0)
.RE
.PP
+\fBmaxclassrepeat\fR
+.RS 4
+The maximum number of allowed consecutive characters of the same class in the
+new password.
+The check is disabled if the value is 0. (default 0)
+.RE
+.PP
+\fBgecoscheck\fR
+.RS 4
+If nonzero, check whether the words longer than 3 characters from the GECOS
+field of the user's passwd entry are contained in the new password.
+The check is disabled if the value is 0. (default 0)
+.RE
+.PP
\fBdictpath\fR
.RS 4
Path to the cracklib dictionaries. Default is to use the cracklib default.
diff -r bc63c08e8a10 -r d84f87223ebb po/cs.po
--- a/po/cs.po Fri Nov 11 12:28:16 2011 +0100
+++ b/po/cs.po Tue Dec 06 21:07:55 2011 +0100
@@ -38,9 +38,8 @@
msgstr "ŠPATNÉ HESLO: %s"
#: src/pwscore.c:21
-#, fuzzy, c-format
msgid "Usage: %s [user]\n"
-msgstr "Použití: %s\n"
+msgstr "Použití: %s [uživatel]\n"
#: src/pwscore.c:22
#, c-format
@@ -96,9 +95,8 @@
msgstr "Heslo je příliš podobné předcházejícímu"
#: src/error.c:45
-#, fuzzy
msgid "The password contains the user name in some form"
-msgstr "Heslo obsahuje příliš málo velkých písmen"
+msgstr "Heslo obsahuje uživatelské jméno v nějaké formě"
#: src/error.c:48
#, c-format
diff -r bc63c08e8a10 -r d84f87223ebb src/check.c
--- a/src/check.c Fri Nov 11 12:28:16 2011 +0100
+++ b/src/check.c Tue Dec 06 21:07:55 2011 +0100
@@ -10,6 +10,9 @@
#include <string.h>
#include <ctype.h>
#include <crack.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <unistd.h>
#include "pwquality.h"
#include "pwqprivate.h"
@@ -199,16 +202,47 @@
int others = 0;
int size;
int i;
+ enum { NONE, DIGIT, UCASE, LCASE, OTHER } prevclass = NONE;
+ int sameclass = 0;
for (i = 0; new[i]; i++) {
- if (isdigit(new[i]))
+ if (isdigit(new[i])) {
digits++;
- else if (isupper(new[i]))
+ if (prevclass != DIGIT) {
+ prevclass = DIGIT;
+ sameclass = 1;
+ } else
+ sameclass++;
+ }
+ else if (isupper(new[i])) {
uppers++;
- else if (islower(new[i]))
+ if (prevclass != UCASE) {
+ prevclass = UCASE;
+ sameclass = 1;
+ } else
+ sameclass++;
+ }
+ else if (islower(new[i])) {
lowers++;
- else
+ if (prevclass != LCASE) {
+ prevclass = LCASE;
+ sameclass = 1;
+ } else
+ sameclass++;
+ }
+ else {
others++;
+ if (prevclass != OTHER) {
+ prevclass = OTHER;
+ sameclass = 1;
+ } else
+ sameclass++;
+ }
+ if (pwq->max_class_repeat > 1 && sameclass >
pwq->max_class_repeat) {
+ if (auxerror)
+ *auxerror = (void *)(long)pwq->max_class_repeat;
+ return PWQ_ERROR_MAX_CLASS_REPEAT;
+ }
}
if ((pwq->dig_credit >= 0) && (digits > pwq->dig_credit))
@@ -296,8 +330,9 @@
return 0;
}
-static int usercheck(pwquality_settings_t *pwq, const char *new,
- char *user)
+static int
+usercheck(pwquality_settings_t *pwq, const char *new,
+ char *user)
{
char *f, *b;
int dist;
@@ -346,6 +381,50 @@
return string;
}
+static int
+gecoscheck(pwquality_settings_t *pwq, const char *new,
+ const char *user)
+{
+ struct passwd pwd;
+ struct passwd *result;
+ char *buf;
+ size_t bufsize;
+ char *p;
+ char *next;
+
+ bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (bufsize == -1 || bufsize > PWQ_MAX_PASSWD_BUF_LEN)
+ bufsize = PWQ_MAX_PASSWD_BUF_LEN;
+ buf = malloc(bufsize);
+ if (buf == NULL)
+ return PWQ_ERROR_MEM_ALLOC;
+
+ if (getpwnam_r(user, &pwd, buf, bufsize, &result) != 0 ||
+ result == NULL) {
+ free(buf);
+ return 0;
+ }
+
+ for (p = result->pw_gecos;;p = next + 1) {
+ next = strchr(p, ' ');
+ if (next)
+ *next = '\0';
+
+ if (strlen(p) >= PWQ_MIN_WORD_LENGTH) {
+ str_lower(p);
+ if (usercheck(pwq, new, p)) {
+ free(buf);
+ return PWQ_ERROR_GECOS_CHECK;
+ }
+ }
+
+ if (!next)
+ break;
+ }
+
+ return 0;
+}
+
static char *
x_strdup(const char *string)
{
@@ -413,6 +492,9 @@
if (!rv && usermono && usercheck(pwq, newmono, usermono))
rv = PWQ_ERROR_USER_CHECK;
+ if (!rv && user && pwq->gecos_check)
+ rv = gecoscheck(pwq, newmono, user);
+
if (newmono) {
memset(newmono, 0, strlen(newmono));
free(newmono);
diff -r bc63c08e8a10 -r d84f87223ebb src/error.c
--- a/src/error.c Fri Nov 11 12:28:16 2011 +0100
+++ b/src/error.c Tue Dec 06 21:07:55 2011 +0100
@@ -43,6 +43,8 @@
return _("The password is too similar to the old one");
case PWQ_ERROR_USER_CHECK:
return _("The password contains the user name in some form");
+ case PWQ_ERROR_GECOS_CHECK:
+ return _("The password contains words from the real name of the user
in some form");
case PWQ_ERROR_MIN_DIGITS:
if (auxerror) {
snprintf(buf, len, _("The password contains less than %ld
digits"), (long)auxerror);
@@ -87,6 +89,12 @@
return buf;
}
return _("The password contains too many same characters
consecutively");
+ case PWQ_ERROR_MAX_CLASS_REPEAT:
+ if (auxerror) {
+ snprintf(buf, len, _("The password contains more than %ld
characters of the same class consecutively"), (long)auxerror);
+ return buf;
+ }
+ return _("The password contains too many characters of the same
class consecutively");
case PWQ_ERROR_EMPTY_PASSWORD:
return _("No password supplied");
case PWQ_ERROR_RNG:
diff -r bc63c08e8a10 -r d84f87223ebb src/pwqprivate.h
--- a/src/pwqprivate.h Fri Nov 11 12:28:16 2011 +0100
+++ b/src/pwqprivate.h Tue Dec 06 21:07:55 2011 +0100
@@ -21,6 +21,8 @@
int oth_credit;
int min_class;
int max_repeat;
+ int max_class_repeat;
+ int gecos_check;
char *dict_path;
};
@@ -44,6 +46,8 @@
#define PWQ_BASE_MIN_LENGTH 6 /* used when lower than this value of min len is set
*/
#define PWQ_NUM_CLASSES 4
#define PWQ_NUM_GENERATION_TRIES 3 /* how many times to try to generate the random
password if it fails the check */
+#define PWQ_MIN_WORD_LENGTH 4
+#define PWQ_MAX_PASSWD_BUF_LEN 16300
#ifndef PWQUALITY_DEFAULT_CFGFILE
#define PWQUALITY_DEFAULT_CFGFILE "/etc/security/pwquality.conf"
diff -r bc63c08e8a10 -r d84f87223ebb src/pwquality.conf
--- a/src/pwquality.conf Fri Nov 11 12:28:16 2011 +0100
+++ b/src/pwquality.conf Tue Dec 06 21:07:55 2011 +0100
@@ -33,9 +33,18 @@
# password (digits, uppercase, lowercase, others).
# minclass = 0
#
-# The maximum number of allowed consecutive characters in the new password.
+# The maximum number of allowed consecutive same characters in the new password.
# The check is disabled if the value is 0.
# maxrepeat = 0
#
+# The maximum number of allowed consecutive characters of the same class in the
+# new password.
+# The check is disabled if the value is 0.
+# maxclassrepeat = 0
+#
+# Whether to check for the words from the passwd entry GECOS string of the user.
+# The check is enabled if the value is not 0.
+# gecoscheck = 0
+#
# Path to the cracklib dictionaries. Default is to use the cracklib default.
# dictpath =
diff -r bc63c08e8a10 -r d84f87223ebb src/pwquality.h
--- a/src/pwquality.h Fri Nov 11 12:28:16 2011 +0100
+++ b/src/pwquality.h Tue Dec 06 21:07:55 2011 +0100
@@ -19,6 +19,8 @@
#define PWQ_SETTING_MIN_CLASS 8
#define PWQ_SETTING_MAX_REPEAT 9
#define PWQ_SETTING_DICT_PATH 10
+#define PWQ_SETTING_MAX_CLASS_REPEAT 11
+#define PWQ_SETTING_GECOS_CHECK 12
#define PWQ_MAX_ENTROPY_BITS 256
#define PWQ_MIN_ENTROPY_BITS 56
@@ -51,6 +53,8 @@
#define PWQ_ERROR_RNG -23
#define PWQ_ERROR_GENERATION_FAILED -24
#define PWQ_ERROR_USER_CHECK -25
+#define PWQ_ERROR_GECOS_CHECK -26
+#define PWQ_ERROR_MAX_CLASS_REPEAT -27
typedef struct pwquality_settings pwquality_settings_t;
diff -r bc63c08e8a10 -r d84f87223ebb src/settings.c
--- a/src/settings.c Fri Nov 11 12:28:16 2011 +0100
+++ b/src/settings.c Tue Dec 06 21:07:55 2011 +0100
@@ -57,6 +57,8 @@
{ "ocredit", PWQ_SETTING_OTH_CREDIT, PWQ_TYPE_INT},
{ "minclass", PWQ_SETTING_MIN_CLASS, PWQ_TYPE_INT},
{ "maxrepeat", PWQ_SETTING_MAX_REPEAT, PWQ_TYPE_INT},
+ { "maxclassrepeat", PWQ_SETTING_MAX_CLASS_REPEAT, PWQ_TYPE_INT},
+ { "gecoscheck", PWQ_SETTING_GECOS_CHECK, PWQ_TYPE_INT},
{ "dictpath", PWQ_SETTING_DICT_PATH, PWQ_TYPE_STR}
};
@@ -72,6 +74,7 @@
if (strcasecmp(s_map[i].name, name) == 0) {
switch(s_map[i].type) {
case PWQ_TYPE_INT:
+fprintf(stderr, "Value: '%s'", value);
errno = 0;
val = strtol(value, &endptr, 10);
if (errno != 0 || *value == '\0' ||
@@ -195,7 +198,7 @@
strncpy(name, option, len);
name[sizeof(name) - 1] = '\0';
-
+
return set_name_value(pwq, name, value);
}
@@ -232,6 +235,12 @@
case PWQ_SETTING_MAX_REPEAT:
pwq->max_repeat = value;
break;
+ case PWQ_SETTING_MAX_CLASS_REPEAT:
+ pwq->max_class_repeat = value;
+ break;
+ case PWQ_SETTING_GECOS_CHECK:
+ pwq->gecos_check = value;
+ break;
default:
return PWQ_ERROR_NON_INT_SETTING;
}
@@ -294,6 +303,12 @@
case PWQ_SETTING_MAX_REPEAT:
*value = pwq->max_repeat;
break;
+ case PWQ_SETTING_MAX_CLASS_REPEAT:
+ *value = pwq->max_class_repeat;
+ break;
+ case PWQ_SETTING_GECOS_CHECK:
+ *value = pwq->gecos_check;
+ break;
default:
return PWQ_ERROR_NON_INT_SETTING;
}