- char filename[1024];
- char buf[1025];
- char buffer[80];
- char username[32];
- char *pw_rest;
- int mask;
- int continued;
- FILE *fp;
- FILE *out_fp;
- struct stat sb;
- struct flock lock;
-
-#if ENABLE_FEATURE_SHADOWPASSWDS
- if (access(bb_path_shadow_file, F_OK) == 0) {
- snprintf(filename, sizeof filename, "%s", bb_path_shadow_file);
- } else
-#endif
- {
- snprintf(filename, sizeof filename, "%s", bb_path_passwd_file);
- }
-
- fp = fopen(filename, "r+");
- if (fp == 0 || fstat(fileno(fp), &sb)) {
- /* return 0; */
- return 1;
- }
-
- /* Lock the password file before updating */
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
- if (fcntl(fileno(fp), F_SETLK, &lock) < 0) {
- bb_perror_msg("%s", filename);
- return 1;
- }
- lock.l_type = F_UNLCK;
-
- snprintf(buf, sizeof buf, "%s-", filename);
- if (create_backup(buf, fp)) {
- fcntl(fileno(fp), F_SETLK, &lock);
- fclose(fp);
- return 1;
- }
- snprintf(buf, sizeof buf, "%s+", filename);
- mask = umask(0777);
- out_fp = fopen(buf, "w");
- umask(mask);
- if ((!out_fp) || (fchmod(fileno(out_fp), sb.st_mode & 0777))
- || (fchown(fileno(out_fp), sb.st_uid, sb.st_gid))) {
- fcntl(fileno(fp), F_SETLK, &lock);
- fclose(fp);
- fclose(out_fp);
- return 1;
- }
-
- continued = 0;
- snprintf(username, sizeof username, "%s:", pw->pw_name);
- rewind(fp);
- while (!feof(fp)) {
- fgets(buffer, sizeof buffer, fp);
- if (!continued) { /* Check to see if we're updating this line. */
- if (strncmp(username, buffer, strlen(username)) == 0) {
- /* we have a match. */
- pw_rest = strchr(buffer, ':');
- *pw_rest++ = '\0';
- pw_rest = strchr(pw_rest, ':');
- fprintf(out_fp, "%s:%s%s", buffer, crypt_pw, pw_rest);
- } else {
- fputs(buffer, out_fp);
- }
- } else {
- fputs(buffer, out_fp);
- }
- if (buffer[strlen(buffer) - 1] == '\n') {
- continued = 0;
- } else {
- continued = 1;
+ char salt[sizeof("$N$XXXXXXXX")]; /* "$N$XXXXXXXX" or "XX" */
+ char *orig = (char*)"";
+ char *newp = NULL;
+ char *cp = NULL;
+ char *ret = NULL; /* failure so far */
+
+ if (myuid && pw->pw_passwd[0]) {
+ char *encrypted;
+
+ orig = bb_ask_stdin("Old password: "); /* returns ptr to static */
+ if (!orig)
+ goto err_ret;
+ encrypted = pw_encrypt(orig, pw->pw_passwd, 1); /* returns malloced str */
+ if (strcmp(encrypted, pw->pw_passwd) != 0) {
+ syslog(LOG_WARNING, "incorrect password for %s",
+ pw->pw_name);
+ bb_do_delay(FAIL_DELAY);
+ puts("Incorrect password");
+ goto err_ret;