version 1.10, 2005/03/04 15:36:03 |
version 1.11, 2005/05/01 00:05:10 |
|
|
#include <grp.h> |
#include <grp.h> |
#include <paths.h> |
#include <paths.h> |
#include <login_cap.h> |
#include <login_cap.h> |
|
#include <signal.h> |
|
|
struct pattern { |
struct pattern { |
char *match; |
char *match; |
|
|
regex_t rgx; |
regex_t rgx; |
int i, res, min_len; |
int i, res, min_len; |
char *checker; |
char *checker; |
|
char *argp[] = { "sh", "-c", NULL, NULL}; |
int pipefds[2]; |
int pipefds[2]; |
pid_t child; |
pid_t child; |
|
uid_t uid; |
|
gid_t gid; |
|
|
min_len = (int)login_getcapnum(lc, "minpasswordlen", 6, 6); |
min_len = (int)login_getcapnum(lc, "minpasswordlen", 6, 6); |
if (min_len > 0 && strlen(password) < min_len) { |
if (min_len > 0 && strlen(password) < min_len) { |
|
|
return (0); |
return (0); |
} |
} |
|
|
for (i = 0; i < sizeof(patterns) / sizeof(struct pattern); i++) { |
/* External password check program */ |
if (regcomp(&rgx, patterns[i].match, patterns[i].flags) != 0) |
|
continue; |
|
res = regexec(&rgx, password, 0, NULL, 0); |
|
regfree(&rgx); |
|
if (!res) { |
|
printf("%s\nUnusual capitalization, control characters or digits are suggested.\n", patterns[i].response); |
|
return (0); |
|
} |
|
} |
|
|
|
/* If no external checker is specified, just accept the password */ |
|
checker = login_getcapstr(lc, "passwordcheck", NULL, NULL); |
checker = login_getcapstr(lc, "passwordcheck", NULL, NULL); |
if (checker == NULL) |
|
return (1); |
|
|
|
/* Okay, now pass control to an external program */ |
/* Pipes are only used for external checker */ |
if (pipe(pipefds) == -1) { |
if (checker != NULL && pipe(pipefds) == -1) { |
warn("pipe"); |
warn("pipe"); |
goto out; |
goto out; |
} |
} |
|
|
child = fork(); |
/* Check password in low-privileged child */ |
if (child == 0) { |
switch (child = fork()) { |
char *argp[] = { "sh", "-c", NULL, NULL}; |
case -1: |
|
warn("fork"); |
|
goto out; |
|
case 0: |
|
(void)signal(SIGINT, SIG_DFL); |
|
(void)signal(SIGQUIT, SIG_DFL); |
|
uid = getuid(); |
|
gid = getgid(); |
|
if (setresgid(gid, gid, gid) == -1) { |
|
warn("setresgid"); |
|
exit(1); |
|
} |
|
if (setgroups(1, &gid) == -1) { |
|
warn("setgroups"); |
|
exit(1); |
|
} |
|
if (setresuid(uid, uid, uid) == -1) { |
|
warn("setresuid"); |
|
exit(1); |
|
} |
|
|
/* Drop privileges */ |
for (i = 0; i < sizeof(patterns) / sizeof(*patterns); i++) { |
seteuid(getuid()); |
if (regcomp(&rgx, patterns[i].match, |
setuid(getuid()); |
patterns[i].flags) != 0) |
|
continue; |
|
res = regexec(&rgx, password, 0, NULL, 0); |
|
regfree(&rgx); |
|
if (res == 0) { |
|
printf("%s\n", patterns[i].response); |
|
exit(1); |
|
} |
|
} |
|
|
if (dup2(pipefds[0], STDIN_FILENO) == -1) |
/* If no external checker in use, accept the password */ |
exit(1); |
if (checker == NULL) |
|
exit(0); |
|
|
|
/* Otherwise, pass control to checker program */ |
|
argp[2] = checker; |
|
if (dup2(pipefds[0], STDIN_FILENO) == -1) { |
|
warn("dup2"); |
|
exit(1); |
|
} |
close(pipefds[0]); |
close(pipefds[0]); |
close(pipefds[1]); |
close(pipefds[1]); |
|
|
argp[2] = checker; |
if (execv(_PATH_BSHELL, argp) == -1) { |
if (execv(_PATH_BSHELL, argp) == -1) |
warn("exec"); |
exit(1); |
exit(1); |
/* NOT REACHED */ |
} |
} else if (child == -1) { |
/* NOTREACHED */ |
warn("fork"); |
default: |
goto out; |
break; /* parent continues below */ |
} |
} |
close(pipefds[0]); |
|
|
|
/* Send the password to STDIN of child */ |
if (checker != NULL) { |
write(pipefds[1], password, strlen(password) + 1); |
/* Send the password to STDIN of child */ |
close(pipefds[1]); |
close(pipefds[0]); |
|
write(pipefds[1], password, strlen(password) + 1); |
|
close(pipefds[1]); |
|
} |
|
|
/* get the return value from the child */ |
/* get the return value from the child */ |
wait(&child); |
wait(&child); |
if (WIFEXITED(child) && WEXITSTATUS(child) == 0) { |
if (WIFEXITED(child) && WEXITSTATUS(child) == 0) { |
free(checker); |
if (checker != NULL) |
|
free(checker); |
return (1); |
return (1); |
} |
} |
|
|
out: |
out: |
free(checker); |
if (checker != NULL) |
|
free(checker); |
printf("Please use a different password. Unusual capitalization,\n"); |
printf("Please use a different password. Unusual capitalization,\n"); |
printf("control characters, or digits are suggested.\n"); |
printf("control characters, or digits are suggested.\n"); |
|
|
return (0); |
return (0); |
} |
} |
|
|