newkey.c revision 92921
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part.  Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user or with the express written consent of
8 * Sun Microsystems, Inc.
9 *
10 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 *
14 * Sun RPC is provided with no support and without any obligation on the
15 * part of Sun Microsystems, Inc. to assist in its use, correction,
16 * modification or enhancement.
17 *
18 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20 * OR ANY PART THEREOF.
21 *
22 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23 * or profits or other special, indirect and consequential damages, even if
24 * Sun has been advised of the possibility of such damages.
25 *
26 * Sun Microsystems, Inc.
27 * 2550 Garcia Avenue
28 * Mountain View, California  94043
29 */
30#if !defined(lint) && defined(SCCSIDS)
31#if 0
32static char sccsid[] = "@(#)newkey.c 1.8 91/03/11 Copyr 1986 Sun Micro";
33#endif
34static const char rcsid[] =
35  "$FreeBSD: head/usr.bin/newkey/newkey.c 92921 2002-03-22 01:33:25Z imp $";
36#endif
37
38/*
39 * Copyright (C) 1986, Sun Microsystems, Inc.
40 */
41
42/*
43 * Administrative tool to add a new user to the publickey database
44 */
45#include <sys/types.h>
46#include <sys/time.h>
47#include <sys/resource.h>
48#include <rpc/rpc.h>
49#include <rpc/key_prot.h>
50#ifdef YP
51#include <sys/wait.h>
52#include <rpcsvc/yp_prot.h>
53#include <rpcsvc/ypclnt.h>
54#include <netdb.h>
55#endif	/* YP */
56#include <err.h>
57#include <pwd.h>
58#include <stdio.h>
59#include <string.h>
60#include <unistd.h>
61
62#include "extern.h"
63
64#ifdef YP
65#define MAXMAPNAMELEN 256
66#else
67#define	YPOP_CHANGE 1			/* change, do not add */
68#define	YPOP_INSERT 2			/* add, do not change */
69#define	YPOP_DELETE 3			/* delete this entry */
70#define	YPOP_STORE  4			/* add, or change */
71#define	ERR_ACCESS	1
72#define	ERR_MALLOC	2
73#define	ERR_READ	3
74#define	ERR_WRITE	4
75#define	ERR_DBASE	5
76#define	ERR_KEY		6
77#endif
78
79#ifdef YP
80static char YPDBPATH[]="/var/yp";
81static char PKMAP[] = "publickey.byname";
82#else
83static char PKFILE[] = "/etc/publickey";
84static char *err_string();
85#endif	/* YP */
86
87static void usage(void);
88
89int
90main(argc, argv)
91	int argc;
92	char *argv[];
93{
94	char name[MAXNETNAMELEN + 1];
95	char public[HEXKEYBYTES + 1];
96	char secret[HEXKEYBYTES + 1];
97	char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
98	char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
99	int status;
100	char *pass;
101	struct passwd *pw;
102#ifdef undef
103	struct hostent *h;
104#endif
105
106	if (argc != 3 || !(strcmp(argv[1], "-u") == 0 ||
107		strcmp(argv[1], "-h") == 0)) {
108		usage();
109	}
110	if (geteuid() != 0)
111		errx(1, "must be superuser");
112
113#ifdef YP
114	if (chdir(YPDBPATH) < 0)
115		warn("cannot chdir to %s", YPDBPATH);
116#endif	/* YP */
117	if (strcmp(argv[1], "-u") == 0) {
118		pw = getpwnam(argv[2]);
119		if (pw == NULL)
120			errx(1, "unknown user: %s", argv[2]);
121		(void)user2netname(name, (int)pw->pw_uid, (char *)NULL);
122	} else {
123#ifdef undef
124		h = gethostbyname(argv[2]);
125		if (h == NULL)
126			errx(1, "unknown host: %s", argv[1]);
127		(void)host2netname(name, h->h_name, (char *)NULL);
128#else
129		(void)host2netname(name, argv[2], (char *)NULL);
130#endif
131	}
132
133	(void)printf("Adding new key for %s.\n", name);
134	pass = getpass("New password:");
135	genkeys(public, secret, pass);
136
137	memcpy(crypt1, secret, HEXKEYBYTES);
138	memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
139	crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
140	xencrypt(crypt1, pass);
141
142	memcpy(crypt2, crypt1, HEXKEYBYTES + KEYCHECKSUMSIZE + 1);
143	xdecrypt(crypt2, getpass("Retype password:"));
144	if (memcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 ||
145		memcmp(crypt2, secret, HEXKEYBYTES) != 0)
146		errx(1, "password incorrect");
147
148#ifdef YP
149	(void)printf("Please wait for the database to get updated...\n");
150#endif
151	if ((status = setpublicmap(name, public, crypt1))) {
152#ifdef YP
153		errx(1, "unable to update NIS database (%u): %s",
154			status, yperr_string(status));
155#else
156		errx(1, "unable to update publickey database (%u): %s",
157			status, err_string(status));
158#endif
159	}
160	(void)printf("Your new key has been successfully stored away.\n");
161	exit(0);
162	/* NOTREACHED */
163}
164
165static void
166usage()
167{
168	(void)fprintf(stderr, "%s\n%s\n",
169		"usage: newkey [-u username]",
170		"       newkey [-h hostname]");
171	exit(1);
172}
173
174/*
175 * Set the entry in the public key file
176 */
177int
178setpublicmap(name, public, secret)
179	char *name;
180	char *public;
181	char *secret;
182{
183	char pkent[1024];
184
185	(void)sprintf(pkent, "%s:%s", public, secret);
186#ifdef YP
187	return (mapupdate(name, PKMAP, YPOP_STORE,
188		strlen(name), name, strlen(pkent), pkent));
189#else
190	return (localupdate(name, PKFILE, YPOP_STORE,
191		strlen(name), name, strlen(pkent), pkent));
192#endif
193	}
194
195#ifndef YP
196	/*
197	 * This returns a pointer to an error message string appropriate
198	 * to an input error code.  An input value of zero will return
199	 * a success message.
200	 */
201static char *
202err_string(code)
203	int code;
204{
205	char *pmesg;
206
207	switch (code) {
208	case 0:
209		pmesg = "update operation succeeded";
210		break;
211	case ERR_KEY:
212		pmesg = "no such key in file";
213		break;
214	case ERR_READ:
215		pmesg = "cannot read the database";
216		break;
217	case ERR_WRITE:
218		pmesg = "cannot write to the database";
219		break;
220	case ERR_DBASE:
221		pmesg = "cannot update database";
222		break;
223	case ERR_ACCESS:
224		pmesg = "permission denied";
225		break;
226	case ERR_MALLOC:
227		pmesg = "malloc failed";
228		break;
229	default:
230		pmesg = "unknown error";
231		break;
232	}
233	return (pmesg);
234}
235#endif
236