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
31#if !defined(lint) && defined(SCCSIDS)
32#if 0
33static char sccsid[] = "@(#)newkey.c 1.8 91/03/11 Copyr 1986 Sun Micro";
34#endif
35#endif
36
37/*
38 * Copyright (C) 1986, Sun Microsystems, Inc.
39 */
40
41/*
42 * Administrative tool to add a new user to the publickey database
43 */
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD$");
46
47#include <sys/types.h>
48#include <sys/time.h>
49#include <sys/resource.h>
50
51#include <rpc/rpc.h>
52#include <rpc/key_prot.h>
53
54#ifdef YP
55#include <sys/wait.h>
56#include <rpcsvc/yp_prot.h>
57#include <rpcsvc/ypclnt.h>
58#include <netdb.h>
59#endif	/* YP */
60
61#include <err.h>
62#include <pwd.h>
63#include <stdio.h>
64#include <stdlib.h>
65#include <string.h>
66#include <unistd.h>
67
68#include "extern.h"
69
70#ifdef YP
71#define MAXMAPNAMELEN 256
72#else
73#define	YPOP_CHANGE 1			/* change, do not add */
74#define	YPOP_INSERT 2			/* add, do not change */
75#define	YPOP_DELETE 3			/* delete this entry */
76#define	YPOP_STORE  4			/* add, or change */
77#define	ERR_ACCESS	1
78#define	ERR_MALLOC	2
79#define	ERR_READ	3
80#define	ERR_WRITE	4
81#define	ERR_DBASE	5
82#define	ERR_KEY		6
83#endif
84
85#ifdef YP
86static char YPDBPATH[]="/var/yp";
87static char PKMAP[] = "publickey.byname";
88#else
89static char PKFILE[] = "/etc/publickey";
90static const char *err_string(int);
91#endif	/* YP */
92
93static void usage(void);
94
95int
96main(int argc, char *argv[])
97{
98	char name[MAXNETNAMELEN + 1];
99	char public[HEXKEYBYTES + 1];
100	char secret[HEXKEYBYTES + 1];
101	char crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
102	char crypt2[HEXKEYBYTES + KEYCHECKSUMSIZE + 1];
103	int status;
104	char *pass;
105	struct passwd *pw;
106#ifdef undef
107	struct hostent *h;
108#endif
109
110	if (argc != 3 || !(strcmp(argv[1], "-u") == 0 ||
111		strcmp(argv[1], "-h") == 0)) {
112		usage();
113	}
114	if (geteuid() != 0)
115		errx(1, "must be superuser");
116
117#ifdef YP
118	if (chdir(YPDBPATH) < 0)
119		warn("cannot chdir to %s", YPDBPATH);
120#endif	/* YP */
121	if (strcmp(argv[1], "-u") == 0) {
122		pw = getpwnam(argv[2]);
123		if (pw == NULL)
124			errx(1, "unknown user: %s", argv[2]);
125		(void)user2netname(name, (int)pw->pw_uid, (char *)NULL);
126	} else {
127#ifdef undef
128		h = gethostbyname(argv[2]);
129		if (h == NULL)
130			errx(1, "unknown host: %s", argv[1]);
131		(void)host2netname(name, h->h_name, (char *)NULL);
132#else
133		(void)host2netname(name, argv[2], (char *)NULL);
134#endif
135	}
136
137	(void)printf("Adding new key for %s.\n", name);
138	pass = getpass("New password:");
139	genkeys(public, secret, pass);
140
141	memcpy(crypt1, secret, HEXKEYBYTES);
142	memcpy(crypt1 + HEXKEYBYTES, secret, KEYCHECKSUMSIZE);
143	crypt1[HEXKEYBYTES + KEYCHECKSUMSIZE] = 0;
144	xencrypt(crypt1, pass);
145
146	memcpy(crypt2, crypt1, HEXKEYBYTES + KEYCHECKSUMSIZE + 1);
147	xdecrypt(crypt2, getpass("Retype password:"));
148	if (memcmp(crypt2, crypt2 + HEXKEYBYTES, KEYCHECKSUMSIZE) != 0 ||
149		memcmp(crypt2, secret, HEXKEYBYTES) != 0)
150		errx(1, "password incorrect");
151
152#ifdef YP
153	(void)printf("Please wait for the database to get updated...\n");
154#endif
155	if ((status = setpublicmap(name, public, crypt1))) {
156#ifdef YP
157		errx(1, "unable to update NIS database (%u): %s",
158			status, yperr_string(status));
159#else
160		errx(1, "unable to update publickey database (%u): %s",
161			status, err_string(status));
162#endif
163	}
164	(void)printf("Your new key has been successfully stored away.\n");
165	exit(0);
166	/* NOTREACHED */
167}
168
169static void
170usage(void)
171{
172	(void)fprintf(stderr, "%s\n%s\n",
173		"usage: newkey -h hostname",
174		"       newkey -u username");
175	exit(1);
176}
177
178/*
179 * Set the entry in the public key file
180 */
181int
182setpublicmap(char *name, char *public, char *secret)
183{
184	char pkent[1024];
185
186	(void)sprintf(pkent, "%s:%s", public, secret);
187#ifdef YP
188	return (mapupdate(name, PKMAP, YPOP_STORE,
189		strlen(name), name, strlen(pkent), pkent));
190#else
191	return (localupdate(name, PKFILE, YPOP_STORE,
192		strlen(name), name, strlen(pkent), pkent));
193#endif
194	}
195
196#ifndef YP
197	/*
198	 * This returns a pointer to an error message string appropriate
199	 * to an input error code.  An input value of zero will return
200	 * a success message.
201	 */
202static const char *
203err_string(int code)
204{
205	const 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