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/ |