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}