如何在 macOS 上检查密码?
How to check password on macOS?
以下 C 程序可以检查 Linux 上的用户密码。
但它不适用于 macOS,因为某些功能是 Linux 特定的。
有人可以告诉我如何修改程序以使其在 macOS 上运行吗?
#include <unistd.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *username = argv[1];
struct passwd *pwd = getpwnam(username);
if (pwd == NULL) {
fputs("couldn't get password record", stderr);
return 1;
}
struct spwd *spwd = getspnam(username);
if (spwd == NULL) {
if(errno == EACCES) {
fputs("no permission to read shadow password file", stderr);
return 1;
}
fputs("No such username", stderr);
return 1;
}
char *password = getpass("Password: ");
printf("spwd->sp_pwdp: %s\n", spwd->sp_pwdp);
char *encrypted = crypt(password, spwd->sp_pwdp);
for (char *p = password; *p != '[=10=]'; ++p)
*p = '[=10=]';
if (encrypted == NULL) {
perror("crypt");
return 1;
}
if (strcmp(encrypted, spwd->sp_pwdp) != 0) {
fputs("Incorrect password\n", stderr);
return 1;
}
printf("Successfully authenticated: UID=%d\n", pwd->pw_uid);
return 0;
}
$ sudo ./checkpass "$USER"
Password:
spwd->sp_pwdp: $y$j9T$F5Jx5fExrKuPp53xLKQ..1$X3DX6M94c7o.9agCG9G317fhZg9SqC.5i5rd.RhAtQ7
Successfully authenticated: UID=504
Linux 和 macOS 都使用 PAM 进行身份验证; Linux 使用 Linux-PAM,以及 MacOS 和 BSD OpenPAM。
要通过 PAM 进行身份验证:
/*
This is a variant of the Linux-PAM example at
http://www.linux-pam.org/Linux-PAM-html/adg-example.html
modified to use the 'login' PAM service.
That program was contributed by Shane Watts
[modifications by AGM and kukuk]
Save as ex_login.c, compile using (for Linux-PAM):
gcc -Wall -Wextra -O2 ex_login.c -lpam -lpam_misc -o ex_login
or (for OpenPAM):
gcc -DOPENPAM -Wall -Wextra -O2 ex_login.c -lpam -o ex_login
and run
./ex_login username
to authenticate the specified user.
*/
#include <stdlib.h>
#include <security/pam_appl.h>
#ifdef OPENPAM
#include <security/openpam.h>
#define USE_CONV_FUNC openpam_ttyconv
#else
#include <security/pam_misc.h>
#define USE_CONV_FUNC misc_conv
#endif
#include <stdio.h>
static struct pam_conv conv = {
USE_CONV_FUNC,
NULL
};
int main(int argc, char *argv[])
{
const char *arg0 = (argc > 0 && argv && argv[0] && argv[0][0] != '[=10=]') ? argv[0] : "(this)";
pam_handle_t *pamh = NULL;
int retval;
const char *user;
if (argc != 2) {
fprintf(stderr, "\nUsage: %s USERNAME\n\n", arg0);
exit(EXIT_FAILURE);
}
user = argv[1];
retval = pam_start("login", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "%s: failed to release authenticator\n", arg0);
exit(EXIT_FAILURE);
}
return ( retval == PAM_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE );
}
以下 C 程序可以检查 Linux 上的用户密码。
但它不适用于 macOS,因为某些功能是 Linux 特定的。
有人可以告诉我如何修改程序以使其在 macOS 上运行吗?
#include <unistd.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *username = argv[1];
struct passwd *pwd = getpwnam(username);
if (pwd == NULL) {
fputs("couldn't get password record", stderr);
return 1;
}
struct spwd *spwd = getspnam(username);
if (spwd == NULL) {
if(errno == EACCES) {
fputs("no permission to read shadow password file", stderr);
return 1;
}
fputs("No such username", stderr);
return 1;
}
char *password = getpass("Password: ");
printf("spwd->sp_pwdp: %s\n", spwd->sp_pwdp);
char *encrypted = crypt(password, spwd->sp_pwdp);
for (char *p = password; *p != '[=10=]'; ++p)
*p = '[=10=]';
if (encrypted == NULL) {
perror("crypt");
return 1;
}
if (strcmp(encrypted, spwd->sp_pwdp) != 0) {
fputs("Incorrect password\n", stderr);
return 1;
}
printf("Successfully authenticated: UID=%d\n", pwd->pw_uid);
return 0;
}
$ sudo ./checkpass "$USER"
Password:
spwd->sp_pwdp: $y$j9T$F5Jx5fExrKuPp53xLKQ..1$X3DX6M94c7o.9agCG9G317fhZg9SqC.5i5rd.RhAtQ7
Successfully authenticated: UID=504
Linux 和 macOS 都使用 PAM 进行身份验证; Linux 使用 Linux-PAM,以及 MacOS 和 BSD OpenPAM。
要通过 PAM 进行身份验证:
/*
This is a variant of the Linux-PAM example at
http://www.linux-pam.org/Linux-PAM-html/adg-example.html
modified to use the 'login' PAM service.
That program was contributed by Shane Watts
[modifications by AGM and kukuk]
Save as ex_login.c, compile using (for Linux-PAM):
gcc -Wall -Wextra -O2 ex_login.c -lpam -lpam_misc -o ex_login
or (for OpenPAM):
gcc -DOPENPAM -Wall -Wextra -O2 ex_login.c -lpam -o ex_login
and run
./ex_login username
to authenticate the specified user.
*/
#include <stdlib.h>
#include <security/pam_appl.h>
#ifdef OPENPAM
#include <security/openpam.h>
#define USE_CONV_FUNC openpam_ttyconv
#else
#include <security/pam_misc.h>
#define USE_CONV_FUNC misc_conv
#endif
#include <stdio.h>
static struct pam_conv conv = {
USE_CONV_FUNC,
NULL
};
int main(int argc, char *argv[])
{
const char *arg0 = (argc > 0 && argv && argv[0] && argv[0][0] != '[=10=]') ? argv[0] : "(this)";
pam_handle_t *pamh = NULL;
int retval;
const char *user;
if (argc != 2) {
fprintf(stderr, "\nUsage: %s USERNAME\n\n", arg0);
exit(EXIT_FAILURE);
}
user = argv[1];
retval = pam_start("login", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "%s: failed to release authenticator\n", arg0);
exit(EXIT_FAILURE);
}
return ( retval == PAM_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE );
}