pam_serialnumber.c [plain text]
#define PAM_SM_AUTH
#include <security/pam_modules.h>
#include <security/pam_appl.h>
#include <CoreFoundation/CoreFoundation.h>
#include <AppleSystemInfo/ASI_SerialNumber.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <syslog.h>
#define PASSWORD_PROMPT "Password:"
#define UN_LEN 4
#define FE_MAX 8
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
const char *user;
char *password = NULL;
char serialnumber[128];
struct stat buf;
if (NULL != openpam_get_option(pamh, "serverinstall")) {
if ((0 != stat("/System/Installation/Packages/ServerEssentials.pkg", &buf)) && (0 != stat("/System/Installation/Packages/ASRInstall.pkg", &buf))) {
return PAM_IGNORE;
}
if (0 != stat("/System/Library/CoreServices/ServerVersion.plist", &buf)) {
return PAM_IGNORE;
}
}
if (pam_get_user(pamh, &user, NULL)) {
return PAM_AUTH_ERR;
}
if (0 != strncasecmp(user, "root", UN_LEN)) {
return PAM_AUTH_ERR;
}
CFStringRef cfSerialNumber = ASI_CopyFormattedSerialNumber();
CFMutableStringRef cfMutableSerialNumber = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSerialNumber);
CFRelease(cfSerialNumber);
if (NULL == cfMutableSerialNumber) {
return PAM_AUTHINFO_UNAVAIL;
}
CFStringUppercase(cfMutableSerialNumber, CFLocaleGetSystem());
if (!CFStringGetCString(cfMutableSerialNumber, serialnumber, sizeof(serialnumber), kCFStringEncodingMacRoman)) {
syslog(LOG_ERR, "Authentication error. The serial number could not be read.");
CFRelease(cfMutableSerialNumber);
return PAM_AUTHINFO_UNAVAIL;
}
CFRelease(cfMutableSerialNumber);
if (NULL != openpam_get_option(pamh, "legacy")) {
serialnumber[FE_MAX] = '\0';
}
if (PAM_SUCCESS != pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password)) {
syslog(LOG_ERR, "Authentication error. Unable to get retrieve the password from the PAM context.");
return PAM_AUTH_ERR;
}
if (NULL == password && PAM_SUCCESS != pam_get_authtok(pamh, PAM_AUTHTOK, (const char **)&password, PASSWORD_PROMPT)) {
syslog(LOG_ERR, "Authentication error. Unable to get the password from the user.");
return PAM_AUTH_ERR;
}
if (0 != strcmp(password, serialnumber) && FE_MAX <= strlen(serialnumber)) {
return PAM_AUTH_ERR;
}
memset(password, 0, strlen(password));
return PAM_SUCCESS;
}
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
return PAM_SUCCESS;
}