1 /*-
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1989, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)register.c	8.1 (Berkeley) 06/01/93";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/param.h>
20 #include <sys/time.h>
21 #include <sys/resource.h>
22 #include <sys/socket.h>
23 #include <sys/file.h>
24 #include <sys/signal.h>
25 #include <netinet/in.h>
26 #include <pwd.h>
27 #include <stdio.h>
28 #include <netdb.h>
29 #include <kerberosIV/des.h>
30 #include <kerberosIV/krb.h>
31 #include "pathnames.h"
32 #include "register_proto.h"
33 
34 #define	SERVICE	"krbupdate"	/* service to add to KDC's database */
35 #define	PROTO	"tcp"
36 
37 char	realm[REALM_SZ];
38 char	krbhst[MAX_HSTNM];
39 
40 static	char	pname[ANAME_SZ];
41 static	char	iname[INST_SZ];
42 static	char	password[_PASSWORD_LEN];
43 
44 /* extern char	*sys_errlist; */
45 void	die();
46 void	setup_key(), type_info(), cleanup();
47 
48 main(argc, argv)
49 	int	argc;
50 	char	**argv;
51 {
52 	struct servent	*se;
53 	struct hostent	*host;
54 	struct sockaddr_in	sin, local;
55 	int		rval;
56 	int		sock, llen;
57 	u_char		code;
58 	static struct rlimit rl = { 0, 0 };
59 
60 	signal(SIGPIPE, die);
61 
62 	if (setrlimit(RLIMIT_CORE, &rl) < 0) {
63 		perror("rlimit");
64 		exit(1);
65 	}
66 
67 	if ((se = getservbyname(SERVICE, PROTO)) == NULL) {
68 		fprintf(stderr, "couldn't find entry for service %s\n",
69 			SERVICE);
70 		exit(1);
71 	}
72 	if ((rval = krb_get_lrealm(realm,0)) != KSUCCESS) {
73 		fprintf(stderr, "couldn't get local Kerberos realm: %s\n",
74 			krb_err_txt[rval]);
75 		exit(1);
76 	}
77 
78 	if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) {
79 		fprintf(stderr, "couldn't get Kerberos host: %s\n",
80 			krb_err_txt[rval]);
81 		exit(1);
82 	}
83 
84 	if ((host = gethostbyname(krbhst)) == NULL) {
85 		fprintf(stderr, "couldn't get host entry for host %s\n",
86 			krbhst);
87 		exit(1);
88 	}
89 
90 	sin.sin_family = host->h_addrtype;
91 	(void)bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length);
92 	sin.sin_port = se->s_port;
93 
94 	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
95 		perror("socket");
96 		exit(1);
97 	}
98 
99 	if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
100 		perror("connect");
101 		(void)close(sock);
102 		exit(1);
103 	}
104 
105 	llen = sizeof(local);
106 	if (getsockname(sock, (struct sockaddr *) &local, &llen) < 0) {
107 		perror("getsockname");
108 		(void)close(sock);
109 		exit(1);
110 	}
111 
112 	setup_key(local);
113 
114 	type_info();
115 
116 	if (!get_user_info()) {
117 		code = ABORT;
118 		(void)des_write(sock, &code, 1);
119 		cleanup();
120 		exit(1);
121 	}
122 
123 	code = APPEND_DB;
124 	if (des_write(sock, &code, 1) != 1) {
125 		perror("write 1");
126 		cleanup();
127 		exit(1);
128 	}
129 
130 	if (des_write(sock, pname, ANAME_SZ) != ANAME_SZ) {
131 		perror("write principal name");
132 		cleanup();
133 		exit(1);
134 	}
135 
136 	if (des_write(sock, iname, INST_SZ) != INST_SZ) {
137 		perror("write instance name");
138 		cleanup();
139 		exit(1);
140 	}
141 
142 	if (des_write(sock, password, 255) != 255) {
143 		perror("write password");
144 		cleanup();
145 		exit(1);
146 	}
147 
148 	/* get return message */
149 
150 	{
151 		int	cc;
152 		char	msgbuf[BUFSIZ];
153 
154 		cc = read(sock, msgbuf, BUFSIZ);
155 		if (cc <= 0) {
156 			fprintf(stderr, "protocol error during key verification\n");
157 			cleanup();
158 			exit(1);
159 		}
160 		if (strncmp(msgbuf, GOTKEY_MSG, 6) != 0) {
161 			fprintf(stderr, "%s: %s", krbhst, msgbuf);
162 			cleanup();
163 			exit(1);
164 		}
165 
166 		cc = des_read(sock, msgbuf, BUFSIZ);
167 		if (cc <= 0) {
168 			fprintf(stderr, "protocol error during read\n");
169 			cleanup();
170 			exit(1);
171 		} else {
172 			printf("%s: %s", krbhst, msgbuf);
173 		}
174 	}
175 
176 	cleanup();
177 	(void)close(sock);
178 }
179 
180 void
181 cleanup()
182 {
183 	bzero(password, 255);
184 }
185 
186 extern	char	*crypt();
187 extern	char	*getpass();
188 
189 int
190 get_user_info()
191 {
192 	int	uid = getuid();
193 	int	valid = 0, i;
194 	struct	passwd	*pw;
195 	char	*pas, *namep;
196 
197 	/* NB: we must run setuid-root to get at the real pw file */
198 
199 	if ((pw = getpwuid(uid)) == NULL) {
200 		fprintf(stderr, "Who are you?\n");
201 		return(0);
202 	}
203 	(void)seteuid(uid);
204 	(void)strcpy(pname, pw->pw_name);	/* principal name */
205 
206 	for (i = 1; i < 3; i++) {
207 		pas = getpass("login password:");
208 		namep = crypt(pas, pw->pw_passwd);
209 		if (strcmp(namep, pw->pw_passwd)) {
210 			fprintf(stderr, "Password incorrect\n");
211 			continue;
212 		} else {
213 			valid = 1;
214 			break;
215 		}
216 	}
217 	if (!valid)
218 		return(0);
219 	pas = getpass("Kerberos password (may be the same):");
220 	while (*pas == NULL) {
221 		printf("<NULL> password not allowed\n");
222 		pas = getpass("Kerberos password (may be the same):");
223 	}
224 	(void)strcpy(password, pas);		/* password */
225 	pas = getpass("Retype Kerberos password:");
226 	if (strcmp(password, pas)) {
227 		fprintf(stderr, "Password mismatch -- aborted\n");
228 		return(0);
229 	}
230 
231 	iname[0] = NULL;	/* null instance name */
232 	return(1);
233 }
234 
235 void
236 setup_key(local)
237 	struct	sockaddr_in	local;
238 {
239 	static	struct	keyfile_data	kdata;
240 	static  Key_schedule		schedule;
241 	int	fd;
242 	char	namebuf[MAXPATHLEN];
243 	extern int errno;
244 
245 	(void) sprintf(namebuf, "%s%s",
246 		CLIENT_KEYFILE,
247 		inet_ntoa(local.sin_addr));
248 
249 	fd = open(namebuf, O_RDONLY);
250 	if (fd < 0) {
251 		fprintf(stderr, "couldn't open key file %s for local host: ",
252 			namebuf);
253 		perror("");
254 		exit(1);
255 	}
256 
257 	if (read(fd, (char *)&kdata, sizeof(kdata)) != sizeof(kdata)) {
258 		fprintf(stderr,"size error reading key file for local host %s\n",
259 			inet_ntoa(local.sin_addr));
260 		exit(1);
261 	}
262 	key_sched(kdata.kf_key, schedule);
263 	des_set_key(kdata.kf_key, schedule);
264 	return;
265 }
266 
267 void
268 type_info()
269 {
270 	printf("Kerberos user registration (realm %s)\n\n", realm);
271 	printf("Please enter your login password followed by your new Kerberos password.\n");
272 	printf("The Kerberos password you enter now will be used in the future\n");
273 	printf("as your Kerberos password for all machines in the %s realm.\n", realm);
274 	printf("You will only be allowed to perform this operation once, although you may run\n");
275 	printf("the %s program from now on to change your Kerberos password.\n\n", _PATH_KPASSWD);
276 }
277 
278 void
279 die()
280 {
281 	fprintf(stderr, "\nServer no longer listening\n");
282 	fflush(stderr);
283 	cleanup();
284 	exit(1);
285 }
286