pam_pwquality.c   pam_pwquality.c 
skipping to change at line 19 skipping to change at line 19
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h> #include <limits.h>
#include <syslog.h> #include <syslog.h>
#include <libintl.h> #include <libintl.h>
#include <stdio.h>
#include <pwd.h>
#include <errno.h>
#include "pwquality.h" #include "pwquality.h"
/* For Translators: "%s%s" could be replaced with "<service> " or "". */ /* For Translators: "%s%s" could be replaced with "<service> " or "". */
#define PROMPT1 _("New %s%spassword: ") #define PROMPT1 _("New %s%spassword: ")
/* For Translators: "%s%s" could be replaced with "<service> " or "". */ /* For Translators: "%s%s" could be replaced with "<service> " or "". */
#define PROMPT2 _("Retype new %s%spassword: ") #define PROMPT2 _("Retype new %s%spassword: ")
#define MISTYPED_PASS _("Sorry, passwords do not match.") #define MISTYPED_PASS _("Sorry, passwords do not match.")
/* /*
* here, we make a definition for the externally accessible function * here, we make a definition for the externally accessible function
skipping to change at line 46 skipping to change at line 49
#include <security/pam_modules.h> #include <security/pam_modules.h>
#include <security/_pam_macros.h> #include <security/_pam_macros.h>
#include <security/pam_ext.h> #include <security/pam_ext.h>
/* argument parsing */ /* argument parsing */
#define PAM_DEBUG_ARG 0x0001 #define PAM_DEBUG_ARG 0x0001
struct module_options { struct module_options {
int retry_times; int retry_times;
int enforce_for_root; int enforce_for_root;
int local_users_only;
pwquality_settings_t *pwq; pwquality_settings_t *pwq;
}; };
#define CO_RETRY_TIMES 1 #define CO_RETRY_TIMES 1
#define PATH_PASSWD "/etc/passwd"
static int static int
_pam_parse (pam_handle_t *pamh, struct module_options *opt, _pam_parse (pam_handle_t *pamh, struct module_options *opt,
int argc, const char **argv) int argc, const char **argv)
{ {
int ctrl = 0; int ctrl = 0;
int rv; int rv;
pwquality_settings_t *pwq; pwquality_settings_t *pwq;
void *auxerror; void *auxerror;
char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
skipping to change at line 85 skipping to change at line 91
if (!strcmp(*argv, "debug")) if (!strcmp(*argv, "debug"))
ctrl |= PAM_DEBUG_ARG; ctrl |= PAM_DEBUG_ARG;
else if (!strncmp(*argv, "type=", 5)) else if (!strncmp(*argv, "type=", 5))
pam_set_item (pamh, PAM_AUTHTOK_TYPE, *argv+5); pam_set_item (pamh, PAM_AUTHTOK_TYPE, *argv+5);
else if (!strncmp(*argv, "retry=", 6)) { else if (!strncmp(*argv, "retry=", 6)) {
opt->retry_times = strtol(*argv+6, &ep, 10); opt->retry_times = strtol(*argv+6, &ep, 10);
if (!ep || (opt->retry_times < 1)) if (!ep || (opt->retry_times < 1))
opt->retry_times = CO_RETRY_TIMES; opt->retry_times = CO_RETRY_TIMES;
} else if (!strncmp(*argv, "enforce_for_root", 16)) { } else if (!strncmp(*argv, "enforce_for_root", 16)) {
opt->enforce_for_root = 1; opt->enforce_for_root = 1;
} else if (!strncmp(*argv, "local_users_only", 16)) {
opt->local_users_only = 1;
} else if (!strncmp(*argv, "difignore=", 10)) { } else if (!strncmp(*argv, "difignore=", 10)) {
/* ignored for compatibility with pam_cracklib */ /* ignored for compatibility with pam_cracklib */
} else if (!strncmp(*argv, "reject_username", 15)) { } else if (!strncmp(*argv, "reject_username", 15)) {
/* ignored for compatibility with pam_cracklib */ /* ignored for compatibility with pam_cracklib */
} else if (!strncmp(*argv, "authtok_type", 12)) { } else if (!strncmp(*argv, "authtok_type", 12)) {
/* for pam_get_authtok, ignore */; /* for pam_get_authtok, ignore */;
} else if (!strncmp(*argv, "use_authtok", 11)) { } else if (!strncmp(*argv, "use_authtok", 11)) {
/* for pam_get_authtok, ignore */; /* for pam_get_authtok, ignore */;
} else if (!strncmp(*argv, "use_first_pass", 14)) { } else if (!strncmp(*argv, "use_first_pass", 14)) {
/* for pam_get_authtok, ignore */; /* for pam_get_authtok, ignore */;
skipping to change at line 108 skipping to change at line 116
pam_syslog(pamh, LOG_ERR, pam_syslog(pamh, LOG_ERR,
"pam_parse: unknown or broken option; %s", *argv); "pam_parse: unknown or broken option; %s", *argv);
} }
} }
opt->pwq = pwq; opt->pwq = pwq;
return ctrl; return ctrl;
} }
static int
check_local_user (pam_handle_t *pamh,
const char *user)
{
struct passwd pw, *pwp;
char buf[4096];
int found = 0;
FILE *fp;
int errn;
fp = fopen(PATH_PASSWD, "r");
if (fp == NULL) {
pam_syslog(pamh, LOG_ERR, "unable to open %s: %s",
PATH_PASSWD, pam_strerror(pamh, errno));
return -1;
}
for (;;) {
errn = fgetpwent_r(fp, &pw, buf, sizeof (buf), &pwp);
if (errn == ERANGE) {
pam_syslog(pamh, LOG_WARNING, "%s contains very lon
g lines; corrupted?",
PATH_PASSWD);
/* we can continue here as next call will read furt
her */
continue;
}
if (errn != 0)
break;
if (strcmp(pwp->pw_name, user) == 0) {
found = 1;
break;
}
}
fclose (fp);
if (errn != 0 && errn != ENOENT) {
pam_syslog(pamh, LOG_ERR, "unable to enumerate local accoun
ts: %s",
pam_strerror(pamh, errn));
return -1;
} else {
return found;
}
}
PAM_EXTERN int PAM_EXTERN int
pam_sm_chauthtok(pam_handle_t *pamh, int flags, pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char **argv) int argc, const char **argv)
{ {
int ctrl; int ctrl;
struct module_options options; struct module_options options;
memset(&options, 0, sizeof(options)); memset(&options, 0, sizeof(options));
options.retry_times = CO_RETRY_TIMES; options.retry_times = CO_RETRY_TIMES;
skipping to change at line 172 skipping to change at line 224
retval = pam_get_authtok_noverify(pamh, &newtoken, NULL); retval = pam_get_authtok_noverify(pamh, &newtoken, NULL);
if (retval != PAM_SUCCESS) { if (retval != PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR, "pam_get_authtok_ noverify returned error: %s", pam_syslog(pamh, LOG_ERR, "pam_get_authtok_ noverify returned error: %s",
pam_strerror(pamh, retval)); pam_strerror(pamh, retval));
continue; continue;
} else if (newtoken == NULL) { /* user aborted pass word change, quit */ } else if (newtoken == NULL) { /* user aborted pass word change, quit */
return PAM_AUTHTOK_ERR; return PAM_AUTHTOK_ERR;
} }
/* now test this passwd against libpwquality */ if (options.local_users_only && check_local_user (p
retval = pwquality_check(options.pwq, newtoken, old amh, user) == 0) {
token, user, &auxerror); /* skip the check if a non-local user */
retval = 0;
} else {
/* now test this passwd against libpwqualit
y */
retval = pwquality_check(options.pwq, newto
ken, oldtoken, user, &auxerror);
}
if (retval < 0) { if (retval < 0) {
const char *msg; const char *msg;
char buf[PWQ_MAX_ERROR_MESSAGE_LEN]; char buf[PWQ_MAX_ERROR_MESSAGE_LEN];
msg = pwquality_strerror(buf, sizeof(buf), retval, auxerror); msg = pwquality_strerror(buf, sizeof(buf), retval, auxerror);
if (ctrl & PAM_DEBUG_ARG) if (ctrl & PAM_DEBUG_ARG)
pam_syslog(pamh, LOG_DEBUG, "bad pa ssword: %s", msg); pam_syslog(pamh, LOG_DEBUG, "bad pa ssword: %s", msg);
pam_error(pamh, _("BAD PASSWORD: %s"), msg) ; pam_error(pamh, _("BAD PASSWORD: %s"), msg) ;
if (getuid() || options.enforce_for_root || if (getuid() || options.enforce_for_root ||
skipping to change at line 239 skipping to change at line 296
NULL, NULL,
NULL, NULL,
NULL, NULL,
pam_sm_chauthtok pam_sm_chauthtok
}; };
#endif #endif
/* /*
* Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996. * Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996.
* All rights reserved * All rights reserved
* Copyright (c) Red Hat, Inc, 2011 * Copyright (c) Red Hat, Inc, 2011, 2012
* Copyright (c) Tomas Mraz <tm@t8m.info>, 2011 * Copyright (c) Tomas Mraz <tm@t8m.info>, 2011
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* 1. Redistributions of source code must retain the above copyright * 1. Redistributions of source code must retain the above copyright
* notice, and the entire permission notice in its entirety, * notice, and the entire permission notice in its entirety,
* including the disclaimer of warranties. * including the disclaimer of warranties.
* 2. Redistributions in binary form must reproduce the above copyright * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote * 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior * products derived from this software without specific prior
* written permission. * written permission.
* *
* ALTERNATIVELY, this product may be distributed under the terms of * ALTERNATIVELY, this product may be distributed under the terms of
* the GNU Public License, in which case the provisions of the GPL are * the GNU General Public License version 2 or later, in which case the
* required INSTEAD OF the above restrictions. (This clause is * provisions of the GPL are required INSTEAD OF the above restrictions.
* necessary due to a potential bad interaction between the GPL and
* the restrictions contained in a BSD-style copyright.)
* *
* THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 End of changes. 8 change blocks. 
8 lines changed or deleted 68 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/