4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
39 #pragma ident "%Z%%M% %I% %E% SMI"
42 * Set secret key on local machine
46 #include <rpc/key_prot.h>
47 #include <nfs/nfs.h> /* to revoke existing creds */
48 #include <nfs/nfssys.h>
50 #include <rpcsvc/nis_dhext.h>
52 #define ROOTKEY_FILE "/etc/.rootkey"
53 #define ROOTKEY_FILE_BACKUP "/etc/.rootkey.bak"
54 /* Should last until 16384-bit DH keys */
55 #define MAXROOTKEY_LINE_LEN 4224
56 #define MAXROOTKEY_LEN 4096
58 extern int key_setnet_g();
60 static void logout_curr_key();
63 static char *sec_domain
= NULL
;
64 static char local_domain
[MAXNETNAMELEN
+ 1];
67 * fgets is broken in that if it reads a NUL character it will always return
68 * EOF. This replacement can deal with NULs
71 fgets_ignorenul(char *s
, int n
, FILE *stream
)
73 int fildes
= fileno(stream
);
82 rs
= read(fildes
, &c
, 1);
112 /* write unencrypted secret key into root key file */
114 write_rootkey(char *secret
, char *flavor
, keylen_t keylen
, algtype_t algtype
)
116 char line
[MAXROOTKEY_LINE_LEN
];
117 char keyent
[MAXROOTKEY_LEN
];
119 int rootfd
, bakfd
, hexkeybytes
;
120 bool_t lineone
= TRUE
;
121 bool_t gotit
= FALSE
;
122 FILE *rootfile
, *bakfile
;
124 unlink(ROOTKEY_FILE_BACKUP
);
125 if ((rename(ROOTKEY_FILE
, ROOTKEY_FILE_BACKUP
)) < 0) {
126 if ((bakfd
= creat(ROOTKEY_FILE_BACKUP
, 0600)) < 0) {
127 perror("Could not create /etc/.rootkey.bak");
133 if ((rootfd
= open(ROOTKEY_FILE
, O_WRONLY
+O_CREAT
, 0600)) < 0) {
134 perror("Could not open /etc/.rootkey for writing");
136 "Attempting to restore original /etc/.rootkey\n");
137 (void) rename(ROOTKEY_FILE_BACKUP
, ROOTKEY_FILE
);
140 if (!(rootfile
= fdopen(rootfd
, "w"))) {
141 perror("Could not open /etc/.rootkey for writing");
143 "Attempting to restore original /etc/.rootkey\n");
145 unlink(ROOTKEY_FILE
);
146 rename(ROOTKEY_FILE_BACKUP
, ROOTKEY_FILE
);
149 if (!(bakfile
= fopen(ROOTKEY_FILE_BACKUP
, "r"))) {
150 perror("Could not open /etc/.rootkey.bak for reading");
152 "Attempting to restore original /etc/.rootkey\n");
153 (void) fclose(rootfile
);
154 unlink(ROOTKEY_FILE
);
155 rename(ROOTKEY_FILE_BACKUP
, ROOTKEY_FILE
);
159 hexkeybytes
= ((keylen
+ 7) / 8) * 2;
161 while (fgets_ignorenul(line
, MAXROOTKEY_LINE_LEN
, bakfile
)) {
162 if (sscanf(line
, "%s %d", keyent
, &atent
) < 2) {
164 * No encryption algorithm found in the file
165 * (atent) so default to DES.
167 atent
= AUTH_DES_ALGTYPE
;
170 * 192-bit keys always go on the first line
176 fprintf(rootfile
, "%s\n", secret
);
178 fprintf(rootfile
, "%s", line
);
179 (void) fflush(rootfile
);
181 if ((strlen(keyent
) == hexkeybytes
) &&
182 (atent
== algtype
)) {
184 * Silently remove lines with the same
192 fprintf(rootfile
, "%s %d\n", secret
, algtype
);
194 fprintf(rootfile
, "%s", line
);
195 (void) fflush(rootfile
);
199 /* Append key to rootkey file */
202 fprintf(rootfile
, "%s\n", secret
);
205 fprintf(rootfile
, "\n");
206 fprintf(rootfile
, "%s %d\n", secret
, algtype
);
209 (void) fflush(rootfile
);
212 unlink(ROOTKEY_FILE_BACKUP
);
214 fprintf(stderr
, "Wrote secret key into %s\n", ROOTKEY_FILE
);
216 fprintf(stderr
, "Wrote %s key into %s\n", flavor
,
221 fprintf(stderr
, "WARNING: Could not write %s key to /etc/.rootkey\n",
225 /* Perform AUTH_DES keylogin */
227 oldkeylogin(char *fullname
, char *pass
)
229 char secret
[HEXKEYBYTES
+1];
230 struct key_netstarg netst
;
232 if (getsecretkey(fullname
, secret
, pass
) == 0) {
233 fprintf(stderr
, "Could not find %s's secret key\n",
235 if (sec_domain
&& *sec_domain
&&
236 strcasecmp(sec_domain
, local_domain
)) {
238 "The system default domain '%s' is different from the Secure RPC\n\
239 domain %s where the key is stored. The Secure RPC domainname is\n\
240 defined by the directory object stored in the /var/nis/NIS_COLD_START file.\n\
241 If you need to change this Secure RPC domainname, please use the nisinit(1M)\n\
242 command with the `-k` option.\n", local_domain
, sec_domain
);
245 "Make sure the secret key is stored in domain %s\n",
251 if (secret
[0] == 0) {
252 fprintf(stderr
, "Password incorrect for %s\n",
256 /* revoke any existing (lingering) credentials... */
259 memcpy(netst
.st_priv_key
, secret
, HEXKEYBYTES
);
260 memset(secret
, 0, HEXKEYBYTES
);
262 netst
.st_pub_key
[0] = 0;
263 netst
.st_netname
= strdup(fullname
);
265 /* do actual key login */
266 if (key_setnet(&netst
) < 0) {
267 fprintf(stderr
, "Could not set %s's secret key\n",
269 fprintf(stderr
, "May be the keyserv is down?\n");
270 if (mkrootkey
== 0) /* nothing else to do */
274 /* write unencrypted secret key into root key file */
276 write_rootkey(netst
.st_priv_key
, "des", 192, 0);
282 * Revokes the existing credentials for Secure-RPC and Secure-NFS.
283 * This should only be called if the user entered the correct password;
284 * sorta like the way "su" doesn't force a login if you enter the wrong
291 static char secret
[HEXKEYBYTES
+ 1];
292 struct nfs_revauth_args nra
;
295 * try to revoke the existing key/credentials, assuming
296 * one exists. this will effectively mark "stale" any
297 * cached credientials...
299 if (key_setsecret(secret
) < 0) {
304 * it looks like a credential already existed, so try and
305 * revoke any lingering Secure-NFS privledges.
308 nra
.authtype
= AUTH_DES
;
311 (void) _nfssys(NFS_REVAUTH
, &nra
);
318 fprintf(stderr
, "usage: %s [-r]\n", cmd
);
324 main(int argc
, char *argv
[])
327 char fullname
[MAXNETNAMELEN
+ 1];
331 mechanism_t
**mechlist
;
335 else if (argc
== 2 && (strcmp(argv
[1], "-r") == 0)) {
336 if (geteuid() != 0) {
337 fprintf(stderr
, "Must be root to use -r option.\n");
344 if (getnetname(fullname
) == 0) {
345 fprintf(stderr
, "Could not generate netname\n");
348 sec_domain
= strdup(strchr(fullname
, '@') + 1);
349 getdomainname(local_domain
, MAXNETNAMELEN
);
351 if (!(pass
= getpass("Password:")))
354 if (mechlist
= __nis_get_mechanisms(FALSE
)) {
355 while (mechlist
[i
]) {
358 if (AUTH_DES_COMPAT_CHK(mechlist
[i
])) {
359 (void) oldkeylogin(fullname
, pass
);
364 if (VALID_ALIAS(mechlist
[i
]->alias
))
365 alias
= mechlist
[i
]->alias
;
369 if (getsecretkey_g(fullname
, mechlist
[i
]->keylen
,
370 mechlist
[i
]->algtype
, secret
,
371 (((mechlist
[i
]->keylen
/ 7) +
372 8) * 2) + 1, pass
) == 0) {
374 "WARNING: Could not find %s's %s secret key\n",
380 if (secret
[0] == 0) {
382 "Password incorrect for %s's %s key.\n",
388 if (key_setnet_g(fullname
, secret
,
389 mechlist
[i
]->keylen
, NULL
, 0,
390 mechlist
[i
]->algtype
) < 0) {
392 "Could not set %s's %s secret key\n",
395 "May be the keyserv is down?\n");
400 write_rootkey(secret
, mechlist
[i
]->alias
,
402 mechlist
[i
]->algtype
);
406 exit(oldkeylogin(fullname
, pass
));