xref: /plan9/sys/src/cmd/auth/changeuser.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <ctype.h>
5 #include "authsrv.h"
6 
7 
8 void	install(char*, char*, char*, long, int);
9 int	exists (char*, char*);
10 long	getexpiration(char *db, char *u);
11 Tm	getdate(char*);
12 
13 void
14 usage(void)
15 {
16 	fprint(2, "usage: changeuser [-hpn] user\n");
17 	exits("usage");
18 }
19 
20 void
21 main(int argc, char *argv[])
22 {
23 	char *u, key[DESKEYLEN], answer[32];
24 	int which, i, newkey, newbio;
25 	long t;
26 	Acctbio a;
27 	Fs *f;
28 
29 	srand(getpid()*time(0));
30 	fmtinstall('K', keyconv);
31 
32 	which = 0;
33 	ARGBEGIN{
34 	case 'p':
35 		which |= Plan9;
36 		break;
37 	case 'n':
38 		which |= Securenet;
39 		break;
40 	default:
41 		usage();
42 	}ARGEND
43 	argv0 = "changeuser";
44 
45 	if(argc != 1)
46 		usage();
47 	u = *argv;
48 	if(memchr(u, '\0', NAMELEN) == 0)
49 		error("bad user name");
50 
51 	if(!which)
52 		which = Plan9;
53 
54 	newbio = 0;
55 	t = 0;
56 	a.user = 0;
57 	if(which & Plan9){
58 		f = &fs[Plan9];
59 		newkey = 1;
60 		if(exists(f->keys, u)){
61 			readln("assign new password? [y/n]: ", answer, sizeof answer, 0);
62 			if(answer[0] != 'y' && answer[0] != 'Y')
63 				newkey = 0;
64 		}
65 		if(newkey)
66 			getpass(key, 1);
67 		t = getexpiration(f->keys, u);
68 		install(f->keys, u, key, t, newkey);
69 		newbio = querybio(f->who, u, &a);
70 		if(newbio)
71 			wrbio(f->who, &a);
72 		print("user %s installed for Plan 9\n", u);
73 		syslog(0, AUTHLOG, "user %s installed for plan 9", u);
74 	}
75 	if(which & Securenet){
76 		f = &fs[Securenet];
77 		newkey = 1;
78 		if(exists(f->keys, u)){
79 			readln("assign new key? [y/n]: ", answer, sizeof answer, 0);
80 			if(answer[0] != 'y' && answer[0] != 'Y')
81 				newkey = 0;
82 		}
83 		if(newkey)
84 			for(i=0; i<DESKEYLEN; i++)
85 				key[i] = nrand(256);
86 		if(a.user == 0){
87 			t = getexpiration(f->keys, u);
88 			newbio = querybio(f->who, u, &a);
89 		}
90 		install(f->keys, u, key, t, newkey);
91 		if(newbio)
92 			wrbio(f->who, &a);
93 		findkey(f->keys, u, key);
94 		print("user %s: SecureNet key: %K\n", u, key);
95 		checksum(key, answer);
96 		print("verify with checksum %s\n", answer);
97 		print("user %s installed for SecureNet\n", u);
98 		syslog(0, AUTHLOG, "user %s installed for securenet", u);
99 	}
100 	exits(0);
101 }
102 
103 void
104 install(char *db, char *u, char *key, long t, int newkey)
105 {
106 	char buf[KEYDBBUF+NAMELEN+6];
107 	int fd;
108 
109 	if(!exists(db, u)){
110 		sprint(buf, "%s/%s", db, u);
111 		fd = create(buf, OREAD, 0777|CHDIR);
112 		if(fd < 0)
113 			error("can't create user %s: %r", u);
114 		close(fd);
115 	}
116 
117 	if(newkey){
118 		sprint(buf, "%s/%s/key", db, u);
119 		fd = open(buf, OWRITE);
120 		if(fd < 0 || write(fd, key, DESKEYLEN) != DESKEYLEN)
121 			error("can't set key: %r");
122 		close(fd);
123 	}
124 
125 	if(t == 0)
126 		return;
127 	sprint(buf, "%s/%s/expire", db, u);
128 	fd = open(buf, OWRITE);
129 	if(fd < 0 || fprint(fd, "%d", t) < 0)
130 		error("can't write expiration time");
131 	close(fd);
132 }
133 
134 int
135 exists(char *db, char *u)
136 {
137 	char buf[KEYDBBUF+NAMELEN+6];
138 
139 	sprint(buf, "%s/%s/expire", db, u);
140 	if(access(buf, OREAD) < 0)
141 		return 0;
142 	return 1;
143 }
144 
145 /*
146  * get the date in the format yyyymmdd
147  */
148 Tm
149 getdate(char *d)
150 {
151 	Tm date;
152 	int i;
153 
154 	date.year = date.mon = date.mday = 0;
155 	date.hour = date.min = date.sec = 0;
156 	for(i = 0; i < 8; i++)
157 		if(!isdigit(d[i]))
158 			return date;
159 	date.year = (d[0]-'0')*1000 + (d[1]-'0')*100 + (d[2]-'0')*10 + d[3]-'0';
160 	date.year -= 1900;
161 	d += 4;
162 	date.mon = (d[0]-'0')*10 + d[1]-'0';
163 	d += 2;
164 	date.mday = (d[0]-'0')*10 + d[1]-'0';
165 	return date;
166 }
167 
168 long
169 getexpiration(char *db, char *u)
170 {
171 	char buf[32];
172 	char prompt[128];
173 	char cdate[32];
174 	Tm date;
175 	ulong secs, now, fd;
176 	int n;
177 
178 	/* read current expiration (if any) */
179 	sprint(buf, "%s/%s/expire", db, u);
180 	fd = open(buf, OREAD);
181 	buf[0] = 0;
182 	if(fd >= 0){
183 		n = read(fd, buf, sizeof(buf)-1);
184 		if(n > 0)
185 			buf[n-1] = 0;
186 		close(fd);
187 	}
188 	secs = 0;
189 	if(buf[0]){
190 		if(strncmp(buf, "never", 5)){
191 			secs = atoi(buf);
192 			memmove(&date, localtime(secs), sizeof(date));
193 			sprint(buf, "%4.4d%2.2d%2.2d", date.year+1900, date.mon, date.mday);
194 		} else
195 			buf[5] = 0;
196 	} else
197 		strcpy(buf, "never");
198 	sprint(prompt, "Expiration date (YYYYMMDD or never)[return = %s]: ", buf);
199 
200 	now = time(0);
201 	for(;;){
202 		readln(prompt, cdate, sizeof cdate, 0);
203 		if(*cdate == 0)
204 			return secs;
205 		if(strcmp(cdate, "never") == 0)
206 			return 0;
207 		date = getdate(cdate);
208 		secs = tm2sec(date);
209 		if(secs > now && secs < now + 2*365*24*60*60)
210 			break;
211 		print("expiration time must fall between now and 2 years from now\n");
212 	}
213 	return secs;
214 }
215