master xplshn/aruu / cmd / xsi / passwd.c
  1/* See LICENSE file for copyright and license details. */
  2#include "passwd.h"
  3#include "config.h"
  4#include "text.h"
  5#include "util.h"
  6
  7#include <errno.h>
  8#include <pwd.h>
  9#include <stdio.h>
 10#include <stdlib.h>
 11#include <string.h>
 12#include <sys/stat.h>
 13#include <unistd.h>
 14
 15static void
 16usage(void)
 17{
 18  eprintf("usage: %s [username]\n", argv0);
 19}
 20
 21// ?man passwd: change a user password
 22// ?man arguments: [username]
 23// ?man change the password associated with the calling user or with username
 24int
 25main(int argc, char *argv[])
 26{
 27  struct pwdb_entry ent;
 28  struct passwd    *pw;
 29  char             *inpass, *prevhash = NULL, *newhash = NULL, salt[PW_SALT_MAX];
 30  char             *c1, *c2;
 31  int               status = 1;
 32
 33  ARGBEGIN
 34  {
 35    default:
 36      usage();
 37  }
 38  ARGEND
 39
 40  pw_init();
 41  umask(077);
 42
 43  if (argc == 0)
 44    pw = getpwuid(getuid());
 45  else
 46    pw = getpwnam(argv[0]);
 47  if (!pw) {
 48    if (errno)
 49      eprintf("getpwnam: %s:", argv[0]);
 50    else
 51      eprintf("who are you?\n");
 52  }
 53
 54  if (pwdb_lookup(&ent, pw->pw_name) < 0)
 55    return 1;
 56  prevhash = ent.hash;
 57
 58  if (getuid() != 0) {
 59    if (prevhash[0] == '!' || prevhash[0] == '*')
 60      eprintf("denied\n");
 61    if (prevhash[0] == '\0') {
 62      /* no password set */
 63    } else {
 64      printf("Changing password for %s\n", pw->pw_name);
 65      inpass = getpass("Old password: ");
 66      if (!inpass)
 67        eprintf("getpass:");
 68      if (inpass[0] == '\0')
 69        eprintf("no password supplied\n");
 70      c1 = crypt(inpass, prevhash);
 71      if (!c1)
 72        eprintf("crypt:");
 73      if (strcmp(c1, prevhash) != 0)
 74        eprintf("incorrect password\n");
 75      explicit_bzero(inpass, strlen(inpass));
 76    }
 77  }
 78
 79  inpass = getpass("Enter new password: ");
 80  if (!inpass)
 81    eprintf("getpass:");
 82  if (inpass[0] == '\0')
 83    eprintf("no password supplied\n");
 84
 85  if (prevhash && prevhash[0] != '\0') {
 86    c1 = crypt(inpass, prevhash);
 87    if (c1 && strcmp(c1, prevhash) == 0)
 88      eprintf("password left unchanged\n");
 89  }
 90
 91  if (pw_gensalt(salt, sizeof(salt)) < 0)
 92    eprintf("pw_gensalt:");
 93  c1 = crypt(inpass, salt);
 94  if (!c1)
 95    eprintf("crypt:");
 96  newhash = estrdup(c1);
 97  explicit_bzero(inpass, strlen(inpass));
 98
 99  inpass = getpass("Retype new password: ");
100  if (!inpass)
101    eprintf("getpass:");
102  if (inpass[0] == '\0')
103    eprintf("no password supplied\n");
104  c2 = crypt(inpass, salt);
105  if (!c2)
106    eprintf("crypt:");
107  if (strcmp(c2, newhash) != 0)
108    eprintf("passwords don't match\n");
109  explicit_bzero(inpass, strlen(inpass));
110
111  if (pwdb_update(pw->pw_name, newhash) == 0)
112    status = 0;
113
114  free(newhash);
115  free(ent.name);
116  free(ent.hash);
117  return status;
118}