如何在 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 );
}