xref: /plan9/sys/src/cmd/auth/passwd.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include "authsrv.h"
5 
6 static char *pbmsg = "AS protocol botch";
7 
8 int
9 asrdresp(int fd, char *buf, int len)
10 {
11 	char error[ERRLEN];
12 
13 	if(read(fd, buf, 1) != 1){
14 		werrstr(pbmsg);
15 		return -1;
16 	}
17 
18 	switch(buf[0]){
19 	case AuthOK:
20 		if(readn(fd, buf, len) < 0){
21 			werrstr(pbmsg);
22 			return -1;
23 		}
24 		break;
25 	case AuthErr:
26 		if(readn(fd, error, ERRLEN) < 0){
27 			werrstr(pbmsg);
28 			return -1;
29 		}
30 		error[ERRLEN-1] = 0;
31 		werrstr(error);
32 		return -1;
33 	default:
34 		werrstr(pbmsg);
35 		return -1;
36 	}
37 	return 0;
38 }
39 
40 void
41 main(int argc, char **argv)
42 {
43 	int n, fd;
44 	Ticketreq tr;
45 	Ticket t;
46 	Passwordreq pr;
47 	char tbuf[TICKETLEN];
48 	char key[DESKEYLEN];
49 	char buf[512];
50 	char *s;
51 
52 	ARGBEGIN{
53 	}ARGEND
54 
55 	s = getenv("service");
56 	if(s && strcmp(s, "cpu") == 0){
57 		fprint(2, "passwd must not be run on the cpu server\n");
58 		exits("boofhead");
59 	}
60 
61 	if(argc > 1)
62 		error("usage: passwd [user]");
63 
64 	fd = authdial();
65 	if(fd < 0)
66 		error("protocol botch: %r");
67 
68 	/* send ticket request to AS */
69 	memset(&tr, 0, sizeof(tr));
70 	if(argc == 0)
71 		strcpy(tr.uid, getuser());
72 	else
73 		strcpy(tr.uid, argv[0]);
74 	tr.type = AuthPass;
75 	convTR2M(&tr, buf);
76 	if(write(fd, buf, TICKREQLEN) != TICKREQLEN)
77 		error("protocol botch: %r");
78 	if(asrdresp(fd, buf, TICKETLEN) < 0)
79 		error("%r");
80 	memmove(tbuf, buf, TICKETLEN);
81 
82 	/*
83 	 *  get a password from the user and try to decrypt the
84 	 *  ticket.  If it doesn't work we've got a bad password,
85 	 *  give up.
86 	 */
87 	readln("Password: ", pr.old, sizeof pr.old, 1);
88 	passtokey(key, pr.old);
89 	convM2T(tbuf, &t, key);
90 	if(t.num != AuthTc || strcmp(t.cuid, tr.uid))
91 		error("bad password");
92 
93 	/* loop trying new passwords */
94 	for(;;){
95 		readln("New password: ", pr.new, sizeof pr.new, 1);
96 		readln("Confirm: ", buf, sizeof buf, 1);
97 		if(strcmp(pr.new, buf))
98 			continue;
99 		pr.num = AuthPass;
100 		convPR2M(&pr, buf, t.key);
101 		if(write(fd, buf, PASSREQLEN) != PASSREQLEN)
102 			error("AS protocol botch: %r");
103 		if(asrdresp(fd, buf, 0) == 0)
104 			break;
105 		fprint(2, "refused: %r\n");
106 	}
107 	close(fd);
108 
109 	/* if this is the hostowner's key, try to change the key in the kernel */
110 	n = readfile("/dev/hostowner", buf, sizeof(buf)-1);
111 	if(n > 0){
112 		buf[n] = 0;
113 		if(strcmp(buf, tr.uid) == 0){
114 			passtokey(key, pr.new);
115 			writefile("/dev/key", key, DESKEYLEN);
116 		}
117 	}
118 	exits(0);
119 }
120