xref: /freebsd/usr.bin/newkey/newkey.c (revision 66fd12cf4896eb08ad8e7a2627537f84ead84dd3)
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
33 static 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
86 static char YPDBPATH[]="/var/yp";
87 static char PKMAP[] = "publickey.byname";
88 #else
89 static char PKFILE[] = "/etc/publickey";
90 static const char *err_string(int);
91 #endif	/* YP */
92 
93 static void usage(void) __dead2;
94 
95 int
96 main(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 
169 static void
170 usage(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  */
181 int
182 setpublicmap(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 	 */
202 static const char *
203 err_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