/* passwd.c - Program to update user password.
 *
 * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
 * Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
 *
 * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html

USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))

config PASSWD
  bool "passwd"
  default y
  depends on TOYBOX_SHADOW
  help
    usage: passwd [-a ALGO] [-dlu] <account name>

    update user's authentication tokens. Default : current user

    -a ALGO	Encryption method (des, md5, sha256, sha512) default: des
    -d		Set password to ''
    -l		Lock (disable) account
    -u		Unlock (enable) account
*/

#define FOR_passwd
#include "toys.h"

GLOBALS(
  char *algo;
)

#ifndef _GNU_SOURCE
char *strcasestr(const char *haystack, const char *needle);
#endif

static int str_check(char *s, char *p)
{
  if (strcasestr(s, p) || strcasestr(p, s)) return 1;
  return 0;
}

static void strength_check(char *newp, char *oldp, char *user)
{
  char *msg = NULL;

  if (strlen(newp) < 6) { //Min passwd len
    msg = "too short";
    xprintf("BAD PASSWORD: %s\n",msg);
  }
  if (!newp[0]) return; //passwd is empty

  if (str_check(newp, user)) {
    msg = "user based password";
    xprintf("BAD PASSWORD: %s\n",msg);
  }

  if (oldp[0] && str_check(newp, oldp)) {
    msg = "based on old passwd";
    xprintf("BAD PASSWORD: %s\n",msg);
  }
}

static int verify_passwd(char * pwd)
{
  char * pass;

  if (!pwd) return 1;
  if (pwd[0] == '!' || pwd[0] == '*') return 1;

  pass = crypt(toybuf, pwd);
  if (pass  && !strcmp(pass, pwd)) return 0;

  return 1;
}

static char *new_password(char *oldp, char *user)
{
  char *newp = NULL;

  if (read_password(toybuf, sizeof(toybuf), "New password:"))
    return NULL; //may be due to Ctrl-C

  newp = xstrdup(toybuf);
  strength_check(newp, oldp, user);
  if (read_password(toybuf, sizeof(toybuf), "Retype password:")) {
    free(newp);
    return NULL; //may be due to Ctrl-C
  }

  if (!strcmp(newp, toybuf)) return newp;
  else error_msg("Passwords do not match.\n");
  // Failure Case
  free(newp);
  return NULL;
}

void passwd_main(void)
{
  uid_t myuid;
  struct passwd *pw;
  struct spwd *sp;
  char *name = NULL, *pass = NULL, *encrypted = NULL, *newp = NULL,
       *orig = (char *)"", salt[MAX_SALT_LEN];
  int ret = -1;

  myuid = getuid();
  if (myuid && (toys.optflags & (FLAG_l | FLAG_u | FLAG_d)))
    error_exit("Not root");

  pw = xgetpwuid(myuid);

  if (*toys.optargs) name = toys.optargs[0];
  else name = xstrdup(pw->pw_name);

  pw = xgetpwnam(name);

  if (myuid && (myuid != pw->pw_uid))
    error_exit("You need to be root to change '%s' password\n", name);

  pass = pw->pw_passwd;
  if (pw->pw_passwd[0] == 'x') {
    //get shadow passwd
    sp = getspnam(name);
    if (sp) pass = sp->sp_pwdp;
  }


  if (!(toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) {
    
    if (!(toys.optflags & FLAG_a)) TT.algo = "des";
    if (get_salt(salt, TT.algo) == -1)
      error_exit("Error: Unkown encryption algorithm\n");

    printf("Changing password for %s\n",name);
    if (myuid && pass[0] == '!')
      error_exit("Can't change, password is locked for %s",name);
    if (myuid) {
      //Validate user 

      if (read_password(toybuf, sizeof(toybuf), "Origial password:")) {
        if (!toys.optargs[0]) free(name);
        return;
      }
      orig = toybuf;
      if (verify_passwd(pass)) error_exit("Authentication failed\n");
    }

    orig = xstrdup(orig);

    // Get new password
    newp = new_password(orig, name);
    if (!newp) {
      free(orig);
      if (!toys.optargs[0]) free(name);
      return; //new password is not set well.
    }

    encrypted = crypt(newp, salt);
    free(newp);
    free(orig);
  } else if (toys.optflags & FLAG_l) {
    if (pass[0] == '!') error_exit("password is already locked for %s",name);
    printf("Locking password for %s\n",name);
    encrypted = xmprintf("!%s",pass);
  } else if (toys.optflags & FLAG_u) {
    if (pass[0] != '!') error_exit("password is already unlocked for %s",name);

    printf("Unlocking password for %s\n",name);
    encrypted = xstrdup(&pass[1]);
  } else if (toys.optflags & FLAG_d) {
    printf("Deleting password for %s\n",name);
    encrypted = xstrdup(""); //1 = "", 2 = '\0'
  }

  // Update the passwd
  if (pw->pw_passwd[0] == 'x')
    ret = update_password("/etc/shadow", name, encrypted);
  else ret = update_password("/etc/passwd", name, encrypted);

  if ((toys.optflags & (FLAG_l | FLAG_u | FLAG_d))) free(encrypted);

  if (!toys.optargs[0]) free(name);
  if (!ret) error_msg("Success");
  else error_msg("Failure");
}
