xref: /plan9-contrib/sys/src/cmd/auth/passwd.c (revision 5979f96214a33481f1724725761f2ef3585d2237)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <authsrv.h>
4*5979f962SDavid du Colombier #include <bio.h>
59a747e4fSDavid du Colombier #include "authcmdlib.h"
6219b2ee8SDavid du Colombier 
7219b2ee8SDavid du Colombier static char *pbmsg = "AS protocol botch";
8219b2ee8SDavid du Colombier 
9219b2ee8SDavid du Colombier int
asrdresp(int fd,char * buf,int len)10219b2ee8SDavid du Colombier asrdresp(int fd, char *buf, int len)
11219b2ee8SDavid du Colombier {
129a747e4fSDavid du Colombier 	char error[AERRLEN];
13219b2ee8SDavid du Colombier 
14219b2ee8SDavid du Colombier 	if(read(fd, buf, 1) != 1){
15219b2ee8SDavid du Colombier 		werrstr(pbmsg);
16219b2ee8SDavid du Colombier 		return -1;
17219b2ee8SDavid du Colombier 	}
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier 	switch(buf[0]){
20219b2ee8SDavid du Colombier 	case AuthOK:
21219b2ee8SDavid du Colombier 		if(readn(fd, buf, len) < 0){
22219b2ee8SDavid du Colombier 			werrstr(pbmsg);
23219b2ee8SDavid du Colombier 			return -1;
24219b2ee8SDavid du Colombier 		}
25219b2ee8SDavid du Colombier 		break;
26219b2ee8SDavid du Colombier 	case AuthErr:
279a747e4fSDavid du Colombier 		if(readn(fd, error, AERRLEN) < 0){
28219b2ee8SDavid du Colombier 			werrstr(pbmsg);
29219b2ee8SDavid du Colombier 			return -1;
30219b2ee8SDavid du Colombier 		}
319a747e4fSDavid du Colombier 		error[AERRLEN-1] = 0;
32219b2ee8SDavid du Colombier 		werrstr(error);
33219b2ee8SDavid du Colombier 		return -1;
34219b2ee8SDavid du Colombier 	default:
35219b2ee8SDavid du Colombier 		werrstr(pbmsg);
36219b2ee8SDavid du Colombier 		return -1;
37219b2ee8SDavid du Colombier 	}
38219b2ee8SDavid du Colombier 	return 0;
39219b2ee8SDavid du Colombier }
40219b2ee8SDavid du Colombier 
41219b2ee8SDavid du Colombier void
main(int argc,char ** argv)42219b2ee8SDavid du Colombier main(int argc, char **argv)
43219b2ee8SDavid du Colombier {
443ff48bf5SDavid du Colombier 	int fd;
45219b2ee8SDavid du Colombier 	Ticketreq tr;
46219b2ee8SDavid du Colombier 	Ticket t;
47219b2ee8SDavid du Colombier 	Passwordreq pr;
48219b2ee8SDavid du Colombier 	char tbuf[TICKETLEN];
49219b2ee8SDavid du Colombier 	char key[DESKEYLEN];
50219b2ee8SDavid du Colombier 	char buf[512];
513ff48bf5SDavid du Colombier 	char *s, *user;
523ff48bf5SDavid du Colombier 
533ff48bf5SDavid du Colombier 	user = getuser();
54219b2ee8SDavid du Colombier 
55219b2ee8SDavid du Colombier 	ARGBEGIN{
56219b2ee8SDavid du Colombier 	}ARGEND
57219b2ee8SDavid du Colombier 
589a747e4fSDavid du Colombier 	s = nil;
593ff48bf5SDavid du Colombier 	if(argc > 0){
603ff48bf5SDavid du Colombier 		user = argv[0];
613ff48bf5SDavid du Colombier 		s = strchr(user, '@');
623ff48bf5SDavid du Colombier 		if(s != nil)
633ff48bf5SDavid du Colombier 			*s++ = 0;
643ff48bf5SDavid du Colombier 		if(*user == 0)
653ff48bf5SDavid du Colombier 			user = getuser();
663ff48bf5SDavid du Colombier 	}
67219b2ee8SDavid du Colombier 
689a747e4fSDavid du Colombier 	fd = authdial(nil, s);
69219b2ee8SDavid du Colombier 	if(fd < 0)
70219b2ee8SDavid du Colombier 		error("protocol botch: %r");
71219b2ee8SDavid du Colombier 
72219b2ee8SDavid du Colombier 	/* send ticket request to AS */
73219b2ee8SDavid du Colombier 	memset(&tr, 0, sizeof(tr));
743ff48bf5SDavid du Colombier 	strcpy(tr.uid, user);
75219b2ee8SDavid du Colombier 	tr.type = AuthPass;
76219b2ee8SDavid du Colombier 	convTR2M(&tr, buf);
77219b2ee8SDavid du Colombier 	if(write(fd, buf, TICKREQLEN) != TICKREQLEN)
78219b2ee8SDavid du Colombier 		error("protocol botch: %r");
79219b2ee8SDavid du Colombier 	if(asrdresp(fd, buf, TICKETLEN) < 0)
80219b2ee8SDavid du Colombier 		error("%r");
81219b2ee8SDavid du Colombier 	memmove(tbuf, buf, TICKETLEN);
82219b2ee8SDavid du Colombier 
83219b2ee8SDavid du Colombier 	/*
84219b2ee8SDavid du Colombier 	 *  get a password from the user and try to decrypt the
85219b2ee8SDavid du Colombier 	 *  ticket.  If it doesn't work we've got a bad password,
86219b2ee8SDavid du Colombier 	 *  give up.
87219b2ee8SDavid du Colombier 	 */
887dd7cddfSDavid du Colombier 	readln("Plan 9 Password: ", pr.old, sizeof pr.old, 1);
89219b2ee8SDavid du Colombier 	passtokey(key, pr.old);
90219b2ee8SDavid du Colombier 	convM2T(tbuf, &t, key);
917dd7cddfSDavid du Colombier 	if(t.num != AuthTp || strcmp(t.cuid, tr.uid))
92219b2ee8SDavid du Colombier 		error("bad password");
93219b2ee8SDavid du Colombier 
94219b2ee8SDavid du Colombier 	/* loop trying new passwords */
95219b2ee8SDavid du Colombier 	for(;;){
967dd7cddfSDavid du Colombier 		pr.changesecret = 0;
977dd7cddfSDavid du Colombier 		*pr.new = 0;
987dd7cddfSDavid du Colombier 		readln("change Plan 9 Password? (y/n) ", buf, sizeof buf, 0);
997dd7cddfSDavid du Colombier 		if(*buf == 'y' || *buf == 'Y'){
1007dd7cddfSDavid du Colombier 			readln("Password(8 to 31 characters): ", pr.new,
1017dd7cddfSDavid du Colombier 				sizeof pr.new, 1);
102219b2ee8SDavid du Colombier 			readln("Confirm: ", buf, sizeof buf, 1);
1037dd7cddfSDavid du Colombier 			if(strcmp(pr.new, buf)){
1047dd7cddfSDavid du Colombier 				print("!mismatch\n");
105219b2ee8SDavid du Colombier 				continue;
1067dd7cddfSDavid du Colombier 			}
1077dd7cddfSDavid du Colombier 		}
1087dd7cddfSDavid du Colombier 		readln("change Inferno/POP password? (y/n) ", buf, sizeof buf, 0);
1097dd7cddfSDavid du Colombier 		if(*buf == 'y' || *buf == 'Y'){
1107dd7cddfSDavid du Colombier 			pr.changesecret = 1;
1117dd7cddfSDavid du Colombier 			readln("make it the same as your plan 9 password? (y/n) ",
1127dd7cddfSDavid du Colombier 				buf, sizeof buf, 0);
1137dd7cddfSDavid du Colombier 			if(*buf == 'y' || *buf == 'Y'){
1147dd7cddfSDavid du Colombier 				if(*pr.new == 0)
1157dd7cddfSDavid du Colombier 					strcpy(pr.secret, pr.old);
1167dd7cddfSDavid du Colombier 				else
1177dd7cddfSDavid du Colombier 					strcpy(pr.secret, pr.new);
1187dd7cddfSDavid du Colombier 			} else {
1197dd7cddfSDavid du Colombier 				readln("Secret(0 to 256 characters): ", pr.secret,
1207dd7cddfSDavid du Colombier 					sizeof pr.secret, 1);
1217dd7cddfSDavid du Colombier 				readln("Confirm: ", buf, sizeof buf, 1);
1227dd7cddfSDavid du Colombier 				if(strcmp(pr.secret, buf)){
1237dd7cddfSDavid du Colombier 					print("!mismatch\n");
1247dd7cddfSDavid du Colombier 					continue;
1257dd7cddfSDavid du Colombier 				}
1267dd7cddfSDavid du Colombier 			}
1277dd7cddfSDavid du Colombier 		}
128219b2ee8SDavid du Colombier 		pr.num = AuthPass;
129219b2ee8SDavid du Colombier 		convPR2M(&pr, buf, t.key);
130219b2ee8SDavid du Colombier 		if(write(fd, buf, PASSREQLEN) != PASSREQLEN)
131219b2ee8SDavid du Colombier 			error("AS protocol botch: %r");
132219b2ee8SDavid du Colombier 		if(asrdresp(fd, buf, 0) == 0)
133219b2ee8SDavid du Colombier 			break;
134d854de59SDavid du Colombier 		fprint(2, "passwd: refused: %r\n");
135219b2ee8SDavid du Colombier 	}
136219b2ee8SDavid du Colombier 	close(fd);
137219b2ee8SDavid du Colombier 
138219b2ee8SDavid du Colombier 	exits(0);
139219b2ee8SDavid du Colombier }
140