chkey.c revision 26240
1168054Sflz/*
2168054Sflz * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3168266Sgabor * unrestricted use provided that this legend is included on all tape
4168266Sgabor * media and as a part of the software program in whole or part.  Users
5168266Sgabor * may copy or modify Sun RPC without charge, but are not authorized
6168266Sgabor * to license or distribute it to anyone else except as part of a product or
7168266Sgabor * program developed by the user or with the express written consent of
8168266Sgabor * Sun Microsystems, Inc.
9168266Sgabor *
10168266Sgabor * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11168054Sflz * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12168054Sflz * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13168064Sflz *
14168064Sflz * Sun RPC is provided with no support and without any obligation on the
15168064Sflz * part of Sun Microsystems, Inc. to assist in its use, correction,
16168064Sflz * modification or enhancement.
17168064Sflz *
18168064Sflz * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19168064Sflz * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20168064Sflz * OR ANY PART THEREOF.
21168064Sflz *
22168064Sflz * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23168064Sflz * or profits or other special, indirect and consequential damages, even if
24168064Sflz * Sun has been advised of the possibility of such damages.
25168064Sflz *
26168064Sflz * Sun Microsystems, Inc.
27168054Sflz * 2550 Garcia Avenue
28168054Sflz * Mountain View, California  94043
29168064Sflz */
30168054Sflz#ifndef lint
31168064Sflzstatic char sccsid[] = "@(#)chkey.c 1.7 91/03/11 Copyr 1986 Sun Micro";
32171129Sobrien#endif
33168939Stmclaugh/*
34168131Sbmah * Copyright (C) 1986, Sun Microsystems, Inc.
35168113Smarcus */
36180225Smarcel
37168123Snetchild/*
38168939Stmclaugh * Command to change one's public key in the public key database
39168064Sflz */
40168054Sflz#include <stdio.h>
41168054Sflz#include <rpc/rpc.h>
42168054Sflz#include <rpc/key_prot.h>
43168054Sflz#ifdef YP
44168261Sache#include <rpcsvc/yp_prot.h>
45168077Sflz#include <rpcsvc/ypclnt.h>
46168077Sflz#else
47232357Sak#define	YPOP_STORE	4
48168126Sale#endif
49168069Sgarga#include <pwd.h>
50168472Snovel#include <string.h>
51179877Samdmi3#include <sys/fcntl.h>
52168274Ssem
53169073Saraujoextern char *getpass();
54168667Sstefan#define index strchr
55209039Sashishextern char *crypt();
56203044Savilla#ifdef YPPASSWD
57193190Savlstruct passwd *ypgetpwuid();
58168274Ssem#endif
59210573Sbapt
60188692Sbeat#ifdef YP
61170471Sbeechstatic char *domain;
62168113Smarcusstatic char PKMAP[] = "publickey.byname";
63218631Smiwi#else
64173254Sbrixstatic char PKFILE[] = "/etc/publickey";
65168098Skrion#endif	/* YP */
66168123Snetchildstatic char ROOTKEY[] = "/etc/.rootkey";
67170601Schinsan
68168082Sgargamain(argc, argv)
69168116Sclsung	int argc;
70168937Scperciva	char **argv;
71222995Screes{
72225632Scs	char name[MAXNETNAMELEN+1];
73213988Sculot	char public[HEXKEYBYTES + 1];
74168177Sgabor	char secret[HEXKEYBYTES + 1];
75168354Sdanfe	char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
76168072Sehaupt	char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
77206034Sdecke	int status;
78168108Srafan	char *pass;
79168186Smat	struct passwd *pw;
80218631Smiwi	uid_t uid;
81168210Sitetcu	int force = 0;
82225853Seadler	char *self;
83168068Serwin#ifdef YP
84168072Sehaupt	char *master;
85168113Smarcus#endif
86168059Sgabor
87168542Smiwi	self = argv[0];
88168098Skrion	for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
89216282Sflo		if (argv[0][2] != 0) {
90206495Sfluffy			usage(self);
91168054Sflz		}
92168059Sgabor		switch (argv[0][1]) {
93176595Sgahr		case 'f':
94168054Sflz			force = 1;
95210773Sglarkin			break;
96210773Sglarkin		default:
97172158Sjkim			usage(self);
98172158Sjkim		}
99168256Sijliao	}
100168209Sitetcu	if (argc != 0) {
101206184Sjacula		usage(self);
102176768Sjadawin	}
103236343Sjase
104228752Sjgh#ifdef YP
105172158Sjkim	(void)yp_get_default_domain(&domain);
106222797Sjlaffaye	if (yp_master(domain, PKMAP, &master) != 0) {
107168076Sjmelo		(void)fprintf(stderr,
108168123Snetchild			"can't find master of publickey database\n");
109168054Sflz		exit(1);
110168055Spav	}
111182814Sjpaetzel#endif
112210169Sjsa	uid = getuid() /*geteuid()*/;
113168055Spav	if (uid == 0) {
114168536Skevlo		if (host2netname(name, NULL, NULL) == 0) {
115168177Sgabor			(void)fprintf(stderr,
116168098Skrion			"chkey: cannot convert hostname to netname\n");
117218631Smiwi			exit(1);
118168055Spav		}
119168161Sphilip	} else {
120168054Sflz		if (user2netname(name, uid, NULL) == 0) {
121168208Sitetcu			(void)fprintf(stderr,
122168295Sleeym			"chkey: cannot convert username to netname\n");
123168295Sleeym			exit(1);
124172158Sjkim		}
125175205Sedwin	}
126168939Stmclaugh	(void)printf("Generating new key for %s.\n", name);
127176979Slippe
128218631Smiwi	if (!force) {
129168068Serwin		if (uid != 0) {
130168337Slwhsu#ifdef YPPASSWD
131175205Sedwin			pw = ypgetpwuid(uid);
132234195Smadpilot#else
133168177Sgabor			pw = getpwuid(uid);
134199480Smandree#endif
135199479Smandree			if (pw == NULL) {
136168113Smarcus#ifdef YPPASSWD
137168918Sbrueffer				(void)fprintf(stderr,
138220095Smartymac		"No NIS password entry found: can't change key.\n");
139168186Smat#else
140231275Smatthew				(void)fprintf(stderr,
141168055Spav		"No password entry found: can't change key.\n");
142168098Skrion#endif
143168359Smm				exit(1);
144168100Smnag			}
145218631Smiwi		} else {
146169036Snemoliu			pw = getpwuid(0);
147168123Snetchild			if (pw == NULL) {
148168177Sgabor				(void)fprintf(stderr,
149168134Snork				"No password entry found: can't change key.\n");
150168084Sehaupt				exit(1);
151168542Smiwi			}
152171129Sobrien		}
153236257Solivierd	}
154171129Sobrien	pass = getpass("Password:");
155169253Sfjoe#ifdef YPPASSWD
156168939Stmclaugh	if (!force) {
157168054Sflz		if (strcmp(crypt(pass, pw->pw_passwd), pw->pw_passwd) != 0) {
158219614Spawel			(void)fprintf(stderr, "Invalid password.\n");
159190977Spgj			exit(1);
160168098Skrion		}
161180729Spgollucci	}
162168108Srafan#else
163226351Srakuco	force = 1;	/* Make this mandatory */
164206489Srene#endif
165227417Srm	genkeys(public, secret, pass);
166180983Srnoland
167203046Sromain	memcpy(crypt1, secret, HEXKEYBYTES);
168206532Ssahil	memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
169168098Skrion	crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
170219730Ssbz	xencrypt(crypt1, pass);
171227731Sscheidell
172168098Skrion	if (force) {
173168098Skrion		memcpy(crypt2, crypt1, HEXKEYBYTES + KEYCHECKSUMSIZE + 1);
174168055Spav		xdecrypt(crypt2, getpass("Retype password:"));
175168068Serwin		if (memcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 ||
176191885Sskreuzer		    memcmp(crypt2, secret, HEXKEYBYTES) != 0) {
177168939Stmclaugh			(void)fprintf(stderr, "Password incorrect.\n");
178234343Ssperber			exit(1);
179168290Ssem		}
180168667Sstefan	}
181223090Sstephen
182213001Ssunpoet#ifdef YP
183218631Smiwi	(void)printf("Sending key change request to %s...\n", master);
184212219Sswills#endif
185172276Stabthorpe	status = setpublicmap(name, public, crypt1);
186168125Stdb	if (status != 0) {
187170675Stimur#ifdef YP
188236348Stj		(void)fprintf(stderr,
189192568Stota		"%s: unable to update NIS database (%u): %s\n",
190169018Strasz				self, status, yperr_string(status));
191168225Strhodes#else
192168186Smat		(void)fprintf(stderr,
193168061Sahze		"%s: unable to update publickey database\n", self);
194231128Suqs#endif
195168069Sgarga		exit(1);
196216401Swen	}
197180728Swxs
198168935Stmclaugh	if (uid == 0) {
199195800Syzlin		/*
200224071Szi		 * Root users store their key in /etc/$ROOTKEY so
201172158Sjkim		 * that they can auto reboot without having to be
202168054Sflz		 * around to type a password. Storing this in a file
203168054Sflz		 * is rather dubious: it should really be in the EEPROM
204168064Sflz		 * so it does not go over the net.
205168064Sflz		 */
206168054Sflz		int fd;
207168055Spav
208168055Spav		fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0);
209168055Spav		if (fd < 0) {
210168055Spav			perror(ROOTKEY);
211168055Spav		} else {
212182814Sjpaetzel			char newline = '\n';
213182814Sjpaetzel
214168055Spav			if (write(fd, secret, strlen(secret)) < 0 ||
215168057Sahze			    write(fd, &newline, sizeof(newline)) < 0) {
216168055Spav				(void)fprintf(stderr, "%s: ", ROOTKEY);
217176979Slippe				perror("write");
218180729Spgollucci			}
219176979Slippe		}
220168919Sbrueffer	}
221168667Sstefan
222168667Sstefan	if (key_setsecret(secret) < 0) {
223171129Sobrien		(void)printf("Unable to login with new secret key.\n");
224171129Sobrien		exit(1);
225226351Srakuco	}
226226351Srakuco	(void)printf("Done.\n");
227225848Seadler	exit(0);
228222817Sjlaffaye	/* NOTREACHED */
229222817Sjlaffaye}
230206034Sdecke
231234343Ssperberusage(name)
232231128Suqs	char *name;
233206034Sdecke{
234188837Sbeech	(void)fprintf(stderr, "usage: %s [-f]\n", name);
235188837Sbeech	exit(1);
236188837Sbeech	/* NOTREACHED */
237168939Stmclaugh}
238168939Stmclaugh
239168939Stmclaugh
240218631Smiwi/*
241218631Smiwi * Set the entry in the public key file
242168125Stdb */
243168208Sitetcusetpublicmap(name, public, secret)
244168125Stdb	char *name;
245168337Slwhsu	char *public;
246172275Stabthorpe	char *secret;
247168337Slwhsu{
248228752Sjgh	char pkent[1024];
249234195Smadpilot
250228752Sjgh	(void)sprintf(pkent,"%s:%s", public, secret);
251236348Stj#ifdef YP
252236348Stj	return (yp_update(domain, PKMAP, YPOP_STORE,
253236343Sjase		name, strlen(name), pkent, strlen(pkent)));
254236343Sjase#else
255234343Ssperber	return (localupdate(name, PKFILE, YPOP_STORE,
256234343Ssperber		strlen(name), name, strlen(pkent), pkent));
257169036Snemoliu#endif
258168108Srafan}
259168108Srafan
260168186Smat#ifdef YPPASSWD
261168186Smatstruct passwd *
262232357Sakypgetpwuid(uid)
263236348Stj	uid_t uid;
264232357Sak{
265168938Scperciva	char uidstr[10];
266168068Serwin	char *val;
267175205Sedwin	int vallen;
268175205Sedwin	static struct passwd pw;
269168068Serwin	char *p;
270168072Sehaupt
271220182Smartymac	(void)sprintf(uidstr, "%d", uid);
272168072Sehaupt	if (yp_match(domain, "passwd.byuid", uidstr, strlen(uidstr),
273168274Ssem			&val, &vallen) != 0) {
274168225Strhodes		return (NULL);
275168225Strhodes	}
276173254Sbrix	p = index(val, ':');
277168068Serwin	if (p == NULL) {
278168059Sgabor		return (NULL);
279168068Serwin	}
280168068Serwin	pw.pw_passwd = p + 1;
281168068Serwin	p = index(pw.pw_passwd, ':');
282168059Sgabor	if (p == NULL) {
283168354Sdanfe		return (NULL);
284216282Sflo	}
285168098Skrion	*p = 0;
286169251Sfjoe	return (&pw);
287168098Skrion}
288236343Sjase#endif	/* YPPASSWD */
289236343Sjase