1
2
3
4
5
6
7
8#include "toys.h"
9#include <time.h>
10
11
12int get_salt(char *salt, char *algo)
13{
14 struct {
15 char *type, id, len;
16 } al[] = {{"des", 0, 2}, {"md5", 1, 8}, {"sha256", 5, 16}, {"sha512", 6, 16}};
17 int i;
18
19 for (i = 0; i < ARRAY_LEN(al); i++) {
20 if (!strcmp(algo, al[i].type)) {
21 int len = al[i].len;
22 char *s = salt;
23
24 if (al[i].id) s += sprintf(s, "$%c$", '0'+al[i].id);
25
26
27 xgetrandom(libbuf, ((len*6)+7)/8, 0);
28
29
30 for (i=0; i<len; i++) {
31 int bitpos = i*6, bits = bitpos/8;
32
33 bits = ((libbuf[i]+(libbuf[i+1]<<8)) >> (bitpos&7)) & 0x3f;
34 bits += 46;
35 if (bits > 57) bits += 7;
36 if (bits > 90) bits += 6;
37
38 s[i] = bits;
39 }
40 salt[len] = 0;
41
42 return s-salt;
43 }
44 }
45
46 return -1;
47}
48
49
50int read_password(char *buf, int buflen, char *mesg)
51{
52 struct termios oldtermio;
53 struct sigaction sa, oldsa;
54 int i, ret = 1;
55
56
57
58 memset(&sa, 0, sizeof(sa));
59 sa.sa_handler = generic_signal;
60 sigaction(SIGINT, &sa, &oldsa);
61
62 tcflush(0, TCIFLUSH);
63 xset_terminal(0, 1, 0, &oldtermio);
64
65 xprintf("%s", mesg);
66
67 for (i=0; i < buflen-1; i++) {
68 if ((ret = read(0, buf+i, 1)) < 0 || (!ret && !i)) {
69 i = 0;
70 ret = 1;
71
72 break;
73 } else if (!ret || buf[i] == '\n' || buf[i] == '\r') {
74 ret = 0;
75
76 break;
77 } else if (buf[i] == 8 || buf[i] == 127) i -= i ? 2 : 1;
78 }
79
80
81 sigaction(SIGINT, &oldsa, NULL);
82 tcsetattr(0, TCSANOW, &oldtermio);
83 buf[i] = 0;
84 xputc('\n');
85
86 return ret;
87}
88
89static char *get_nextcolon(char *line, int cnt)
90{
91 while (cnt--) {
92 if (!(line = strchr(line, ':'))) error_exit("Invalid Entry\n");
93 line++;
94 }
95 return line;
96}
97
98
99
100
101
102
103
104
105
106
107
108int update_password(char *filename, char* username, char* entry)
109{
110 char *filenamesfx = NULL, *namesfx = NULL, *shadow = NULL,
111 *sfx = NULL, *line = NULL;
112 FILE *exfp, *newfp;
113 int ret = -1, found = 0, n;
114 struct flock lock;
115 size_t allocated_length;
116
117 shadow = strstr(filename, "shadow");
118 filenamesfx = xmprintf("%s+", filename);
119 sfx = strchr(filenamesfx, '+');
120
121 exfp = fopen(filename, "r+");
122 if (!exfp) {
123 perror_msg("Couldn't open file %s",filename);
124 goto free_storage;
125 }
126
127 *sfx = '-';
128 unlink(filenamesfx);
129 ret = link(filename, filenamesfx);
130 if (ret < 0) error_msg("can't create backup file");
131
132 *sfx = '+';
133 lock.l_type = F_WRLCK;
134 lock.l_whence = SEEK_SET;
135 lock.l_start = 0;
136 lock.l_len = 0;
137
138 ret = fcntl(fileno(exfp), F_SETLK, &lock);
139 if (ret < 0) perror_msg("Couldn't lock file %s",filename);
140
141 lock.l_type = F_UNLCK;
142
143 newfp = fopen(filenamesfx, "w+");
144 if (!newfp) {
145 error_msg("couldn't open file for writing");
146 ret = -1;
147 fclose(exfp);
148 goto free_storage;
149 }
150
151 ret = 0;
152 namesfx = xmprintf("%s:",username);
153 while ((n = getline(&line, &allocated_length, exfp)) > 0) {
154 line[n-1] = 0;
155 if (strncmp(line, namesfx, strlen(namesfx)))
156 fprintf(newfp, "%s\n", line);
157 else if (entry) {
158 char *current_ptr = NULL;
159
160 found = 1;
161 if (!strcmp(toys.which->name, "passwd")) {
162 fprintf(newfp, "%s%s:",namesfx, entry);
163 current_ptr = get_nextcolon(line, 2);
164 if (shadow) {
165 fprintf(newfp, "%u:",(unsigned)(time(NULL))/(24*60*60));
166 current_ptr = get_nextcolon(current_ptr, 1);
167 fprintf(newfp, "%s\n",current_ptr);
168 } else fprintf(newfp, "%s\n",current_ptr);
169 } else if (!strcmp(toys.which->name, "groupadd") ||
170 !strcmp(toys.which->name, "addgroup") ||
171 !strcmp(toys.which->name, "delgroup") ||
172 !strcmp(toys.which->name, "groupdel")){
173 current_ptr = get_nextcolon(line, 3);
174 *current_ptr = '\0';
175 fprintf(newfp, "%s", line);
176 fprintf(newfp, "%s\n", entry);
177 }
178 }
179 }
180 free(line);
181 free(namesfx);
182 if (!found && entry) fprintf(newfp, "%s\n", entry);
183 fcntl(fileno(exfp), F_SETLK, &lock);
184 fclose(exfp);
185
186 errno = 0;
187 fflush(newfp);
188 fsync(fileno(newfp));
189 fclose(newfp);
190 rename(filenamesfx, filename);
191 if (errno) {
192 perror_msg("File Writing/Saving failed: ");
193 unlink(filenamesfx);
194 ret = -1;
195 }
196
197free_storage:
198 free(filenamesfx);
199 return ret;
200}
201