static bool ChangePassword(const char *puser, const char *password, PasswordFormat format) { assert(format == PASSWORD_FORMAT_PLAINTEXT || format == PASSWORD_FORMAT_HASH); bool successful = false; if (format == PASSWORD_FORMAT_PLAINTEXT) { successful = ChangePlaintextPasswordUsingLibPam(puser, password); } else { #ifdef HAVE_CHPASSWD struct stat statbuf; if (stat(CHPASSWD, &statbuf) != -1 && SupportsOption(CHPASSWD, "-e")) { successful = ChangePasswordHashUsingChpasswd(puser, password); } else #endif #if defined(HAVE_LCKPWDF) && defined(HAVE_ULCKPWDF) { successful = ChangePasswordHashUsingLckpwdf(puser, password); } #elif defined(HAVE_CHPASSWD) { Log(LOG_LEVEL_ERR, "No means to set password for user '%s' was found. Tried using the '%s' tool with no luck.", puser, CHPASSWD); successful = false; } #else { Log(LOG_LEVEL_WARNING, "Setting hashed password or locking user '%s' not supported on this platform.", puser); successful = false; } #endif } if (successful) { successful = ClearPasswordAdministrationFlags(puser); } return successful; }
static bool ChangePasswordHashUsingChpasswd(const char *puser, const char *password) { int status; const char *cmd_str = CHPASSWD " -e"; Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s'. (command: '%s')", puser, cmd_str); FILE *cmd = cf_popen_sh(cmd_str, "w"); if (!cmd) { Log(LOG_LEVEL_ERR, "Could not launch password changing command '%s': %s.", cmd_str, GetErrorStr()); return false; } // String lengths plus a ':' and a '\n', but not including '\0'. size_t total_len = strlen(puser) + strlen(password) + 2; char change_string[total_len + 1]; snprintf(change_string, total_len + 1, "%s:%s\n", puser, password); clearerr(cmd); if (fwrite(change_string, total_len, 1, cmd) != 1) { const char *error_str; if (ferror(cmd)) { error_str = GetErrorStr(); } else { error_str = "Unknown error"; } Log(LOG_LEVEL_ERR, "Could not write password to password changing command '%s': %s.", cmd_str, error_str); cf_pclose(cmd); return false; } status = cf_pclose(cmd); if (status) { Log(LOG_LEVEL_ERR, "'%s' returned non-zero status: %i\n", cmd_str, status); return false; } return ClearPasswordAdministrationFlags(puser); }