17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*cb620785Sraf * Common Development and Distribution License (the "License"). 6*cb620785Sraf * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2161961e0fSrobinson 227c478bd9Sstevel@tonic-gate /* 23*cb620785Sraf * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 26e8031f0aSraf 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate /* 307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 317c478bd9Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of 327c478bd9Sstevel@tonic-gate * California. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 38e8031f0aSraf * Interface to keyserver 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate * setsecretkey(key) - set your secret key 417c478bd9Sstevel@tonic-gate * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent 427c478bd9Sstevel@tonic-gate * decryptsessionkey(agent, deskey) - decrypt ditto 437c478bd9Sstevel@tonic-gate * gendeskey(deskey) - generate a secure des key 447c478bd9Sstevel@tonic-gate */ 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include "mt.h" 477c478bd9Sstevel@tonic-gate #include "rpc_mt.h" 487c478bd9Sstevel@tonic-gate #include <errno.h> 497c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 507c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h> 517c478bd9Sstevel@tonic-gate #include <stdio.h> 527c478bd9Sstevel@tonic-gate #include <syslog.h> 537c478bd9Sstevel@tonic-gate #include <string.h> 547c478bd9Sstevel@tonic-gate #include <stdlib.h> 557c478bd9Sstevel@tonic-gate #include <unistd.h> 567c478bd9Sstevel@tonic-gate #include <sys/types.h> 577c478bd9Sstevel@tonic-gate #include <sys/stat.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0)) 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #ifdef DEBUG 627c478bd9Sstevel@tonic-gate #define debug(msg) (void) fprintf(stderr, "%s\n", msg); 637c478bd9Sstevel@tonic-gate #else 647c478bd9Sstevel@tonic-gate #define debug(msg) 657c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate int key_call(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *); 687c478bd9Sstevel@tonic-gate int key_call_ext(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *, int); 697c478bd9Sstevel@tonic-gate int key_setnet(struct key_netstarg *); 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Hack to allow the keyserver to use AUTH_DES (for authenticated 737c478bd9Sstevel@tonic-gate * NIS+ calls, for example). The only functions that get called 747c478bd9Sstevel@tonic-gate * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. 757c478bd9Sstevel@tonic-gate * 767c478bd9Sstevel@tonic-gate * The approach is to have the keyserver fill in pointers to local 777c478bd9Sstevel@tonic-gate * implementations of these functions, and to call those in key_call(). 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate bool_t (*__key_encryptsession_pk_LOCAL)() = NULL; 817c478bd9Sstevel@tonic-gate bool_t (*__key_decryptsession_pk_LOCAL)() = NULL; 827c478bd9Sstevel@tonic-gate bool_t (*__key_gendes_LOCAL)() = NULL; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate int 8661961e0fSrobinson key_setsecret(const char *secretkey) 877c478bd9Sstevel@tonic-gate { 887c478bd9Sstevel@tonic-gate char netName[MAXNETNAMELEN+1]; 897c478bd9Sstevel@tonic-gate struct key_netstarg netst; 907c478bd9Sstevel@tonic-gate int ret; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate if (getnetname(netName) == 0) { 937c478bd9Sstevel@tonic-gate debug("getnetname failed"); 947c478bd9Sstevel@tonic-gate return (-1); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate 9761961e0fSrobinson (void) memcpy(netst.st_priv_key, secretkey, HEXKEYBYTES); 987c478bd9Sstevel@tonic-gate netst.st_pub_key[0] = 0; 997c478bd9Sstevel@tonic-gate netst.st_netname = netName; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * Actual key login 1037c478bd9Sstevel@tonic-gate * We perform the KEY_NET_PUT instead of the SET_KEY 1047c478bd9Sstevel@tonic-gate * rpc call because key_secretkey_is_set function uses 1057c478bd9Sstevel@tonic-gate * the KEY_NET_GET call which expects the netname to be 1067c478bd9Sstevel@tonic-gate * set along with the key. Keylogin also uses KEY_NET_PUT. 1077c478bd9Sstevel@tonic-gate */ 1087c478bd9Sstevel@tonic-gate ret = key_setnet(&netst); 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate /* erase our copy of the secret key */ 11161961e0fSrobinson (void) memset(netst.st_priv_key, '\0', HEXKEYBYTES); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (ret == 1) 1147c478bd9Sstevel@tonic-gate return (0); 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate return (-1); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate int 1207c478bd9Sstevel@tonic-gate key_setsecret_g( 1217c478bd9Sstevel@tonic-gate char *secretkey, 1227c478bd9Sstevel@tonic-gate keylen_t keylen, 1237c478bd9Sstevel@tonic-gate algtype_t algtype, 1247c478bd9Sstevel@tonic-gate des_block userkey) 1257c478bd9Sstevel@tonic-gate { 1267c478bd9Sstevel@tonic-gate setkeyarg3 arg; 1277c478bd9Sstevel@tonic-gate keystatus status; 1287c478bd9Sstevel@tonic-gate 12961961e0fSrobinson if (CLASSIC_PK_DH(keylen, algtype)) 1307c478bd9Sstevel@tonic-gate return (key_setsecret(secretkey)); 1317c478bd9Sstevel@tonic-gate arg.key.keybuf3_len = keylen/4 + 1; 1327c478bd9Sstevel@tonic-gate arg.key.keybuf3_val = secretkey; 1337c478bd9Sstevel@tonic-gate arg.algtype = algtype; 1347c478bd9Sstevel@tonic-gate arg.keylen = keylen; 1357c478bd9Sstevel@tonic-gate arg.userkey = userkey; 1367c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_SET_3, xdr_setkeyarg3, (char *)&arg, 13761961e0fSrobinson xdr_keystatus, (char *)&status)) 1387c478bd9Sstevel@tonic-gate return (-1); 1397c478bd9Sstevel@tonic-gate if (status != KEY_SUCCESS) { 1407c478bd9Sstevel@tonic-gate debug("set3 status is nonzero"); 1417c478bd9Sstevel@tonic-gate return (-1); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate return (0); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate int 1477c478bd9Sstevel@tonic-gate key_removesecret_g_ext(int use_uid) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate keystatus status; 1507c478bd9Sstevel@tonic-gate 15161961e0fSrobinson if (!key_call_ext((rpcproc_t)KEY_CLEAR_3, xdr_void, NULL, 1527c478bd9Sstevel@tonic-gate xdr_keystatus, (char *)&status, use_uid)) { 1537c478bd9Sstevel@tonic-gate debug("remove secret key call failed"); 1547c478bd9Sstevel@tonic-gate return (-1); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate if (status != KEY_SUCCESS) { 1577c478bd9Sstevel@tonic-gate debug("remove secret status is nonzero"); 1587c478bd9Sstevel@tonic-gate return (-1); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate return (0); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* 1647c478bd9Sstevel@tonic-gate * Use effective uid. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate int 16761961e0fSrobinson key_removesecret_g(void) 1687c478bd9Sstevel@tonic-gate { 1697c478bd9Sstevel@tonic-gate return (key_removesecret_g_ext(0)); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* 1737c478bd9Sstevel@tonic-gate * Use real uid. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate int 17661961e0fSrobinson key_removesecret_g_ruid(void) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate return (key_removesecret_g_ext(1)); 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * key_secretkey_is_set() returns 1 if the keyserver has a secret key 1837c478bd9Sstevel@tonic-gate * stored for the caller's effective uid if use_ruid is 0 or 1847c478bd9Sstevel@tonic-gate * stored for the caller's real uid if use_ruid is 1. 1857c478bd9Sstevel@tonic-gate * it returns 0 otherwise. 1867c478bd9Sstevel@tonic-gate * 1877c478bd9Sstevel@tonic-gate * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't 1887c478bd9Sstevel@tonic-gate * be using it, because it allows them to get the user's secret key. 1897c478bd9Sstevel@tonic-gate * 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate int 1927c478bd9Sstevel@tonic-gate key_secretkey_is_set_ext(int use_ruid) 1937c478bd9Sstevel@tonic-gate { 1947c478bd9Sstevel@tonic-gate struct key_netstres kres; 1957c478bd9Sstevel@tonic-gate 19661961e0fSrobinson (void) memset(&kres, 0, sizeof (kres)); 19761961e0fSrobinson if (key_call_ext((rpcproc_t)KEY_NET_GET, xdr_void, NULL, 1987c478bd9Sstevel@tonic-gate xdr_key_netstres, (char *)&kres, use_ruid) && 1997c478bd9Sstevel@tonic-gate (kres.status == KEY_SUCCESS) && 2007c478bd9Sstevel@tonic-gate (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { 2017c478bd9Sstevel@tonic-gate /* avoid leaving secret key in memory */ 20261961e0fSrobinson (void) memset(kres.key_netstres_u.knet.st_priv_key, 0, 20361961e0fSrobinson HEXKEYBYTES); 2047c478bd9Sstevel@tonic-gate xdr_free(xdr_key_netstres, (char *)&kres); 2057c478bd9Sstevel@tonic-gate return (1); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate return (0); 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * Use effective uid. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate int 2147c478bd9Sstevel@tonic-gate key_secretkey_is_set(void) 2157c478bd9Sstevel@tonic-gate { 2167c478bd9Sstevel@tonic-gate return (key_secretkey_is_set_ext(0)); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Use real uid. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate int 2237c478bd9Sstevel@tonic-gate key_secretkey_is_set_ruid(void) 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate return (key_secretkey_is_set_ext(1)); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * key_secretkey_is_set_g_ext() returns 1 if the keyserver has a secret key 2307c478bd9Sstevel@tonic-gate * stored for the caller's uid, it returns 0 otherwise. 2317c478bd9Sstevel@tonic-gate * If (use_ruid == 0), for the caller's effective uid. 2327c478bd9Sstevel@tonic-gate * If (use_ruid == 1), for the caller's real uid. 2337c478bd9Sstevel@tonic-gate * 2347c478bd9Sstevel@tonic-gate * N.B.: The KEY_NET_GET_3 key call is undocumented. Applications shouldn't 2357c478bd9Sstevel@tonic-gate * be using it, because it allows them to get the user's secret key. 2367c478bd9Sstevel@tonic-gate */ 2377c478bd9Sstevel@tonic-gate int 2387c478bd9Sstevel@tonic-gate key_secretkey_is_set_g_ext(keylen_t keylen, algtype_t algtype, int use_ruid) 2397c478bd9Sstevel@tonic-gate { 2407c478bd9Sstevel@tonic-gate mechtype arg; 2417c478bd9Sstevel@tonic-gate key_netstres3 kres; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * key_secretkey_is_set_g_ext is tricky because keylen == 0 2457c478bd9Sstevel@tonic-gate * means check if any key exists for the caller (old/new, 192/1024 ...) 2467c478bd9Sstevel@tonic-gate * Rather than handle this on the server side, we call the old 2477c478bd9Sstevel@tonic-gate * routine if keylen == 0 and try the newer stuff only if that fails 2487c478bd9Sstevel@tonic-gate */ 24961961e0fSrobinson if ((keylen == 0) && key_secretkey_is_set_ext(use_ruid)) 2507c478bd9Sstevel@tonic-gate return (1); 25161961e0fSrobinson if (CLASSIC_PK_DH(keylen, algtype)) 2527c478bd9Sstevel@tonic-gate return (key_secretkey_is_set_ext(use_ruid)); 2537c478bd9Sstevel@tonic-gate arg.keylen = keylen; 2547c478bd9Sstevel@tonic-gate arg.algtype = algtype; 25561961e0fSrobinson (void) memset(&kres, 0, sizeof (kres)); 2567c478bd9Sstevel@tonic-gate if (key_call_ext((rpcproc_t)KEY_NET_GET_3, xdr_mechtype, (char *)&arg, 2577c478bd9Sstevel@tonic-gate xdr_key_netstres3, (char *)&kres, use_ruid) && 2587c478bd9Sstevel@tonic-gate (kres.status == KEY_SUCCESS) && 2597c478bd9Sstevel@tonic-gate (kres.key_netstres3_u.knet.st_priv_key.keybuf3_len != 0)) { 2607c478bd9Sstevel@tonic-gate /* avoid leaving secret key in memory */ 26161961e0fSrobinson (void) memset(kres.key_netstres3_u.knet.st_priv_key.keybuf3_val, 26261961e0fSrobinson 0, kres.key_netstres3_u.knet.st_priv_key.keybuf3_len); 2637c478bd9Sstevel@tonic-gate xdr_free(xdr_key_netstres3, (char *)&kres); 2647c478bd9Sstevel@tonic-gate return (1); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate return (0); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * Use effective uid. 2717c478bd9Sstevel@tonic-gate */ 2727c478bd9Sstevel@tonic-gate int 2737c478bd9Sstevel@tonic-gate key_secretkey_is_set_g(keylen_t keylen, algtype_t algtype) 2747c478bd9Sstevel@tonic-gate { 2757c478bd9Sstevel@tonic-gate return (key_secretkey_is_set_g_ext(keylen, algtype, 0)); 2767c478bd9Sstevel@tonic-gate } 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * Use real uid. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate int 2827c478bd9Sstevel@tonic-gate key_secretkey_is_set_g_ruid(keylen_t keylen, algtype_t algtype) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate return (key_secretkey_is_set_g_ext(keylen, algtype, 1)); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate int 28961961e0fSrobinson key_encryptsession_pk(const char *remotename, netobj *remotekey, 29061961e0fSrobinson des_block *deskey) 2917c478bd9Sstevel@tonic-gate { 2927c478bd9Sstevel@tonic-gate cryptkeyarg2 arg; 2937c478bd9Sstevel@tonic-gate cryptkeyres res; 2947c478bd9Sstevel@tonic-gate 29561961e0fSrobinson arg.remotename = (char *)remotename; 2967c478bd9Sstevel@tonic-gate arg.remotekey = *remotekey; 2977c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 2987c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, 29961961e0fSrobinson xdr_cryptkeyres, (char *)&res)) 3007c478bd9Sstevel@tonic-gate return (-1); 3017c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 3027c478bd9Sstevel@tonic-gate debug("encrypt status is nonzero"); 3037c478bd9Sstevel@tonic-gate return (-1); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 3067c478bd9Sstevel@tonic-gate return (0); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate int 3107c478bd9Sstevel@tonic-gate key_encryptsession_pk_g( 3117c478bd9Sstevel@tonic-gate const char *remotename, 3127c478bd9Sstevel@tonic-gate const char *remotekey, 3137c478bd9Sstevel@tonic-gate keylen_t remotekeylen, 3147c478bd9Sstevel@tonic-gate algtype_t algtype, 3157c478bd9Sstevel@tonic-gate des_block deskey[], 3167c478bd9Sstevel@tonic-gate keynum_t keynum 3177c478bd9Sstevel@tonic-gate ) 3187c478bd9Sstevel@tonic-gate { 3197c478bd9Sstevel@tonic-gate cryptkeyarg3 arg; 3207c478bd9Sstevel@tonic-gate cryptkeyres3 res; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate if (CLASSIC_PK_DH(remotekeylen, algtype)) { 3237c478bd9Sstevel@tonic-gate int i; 3247c478bd9Sstevel@tonic-gate netobj npk; 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate npk.n_len = remotekeylen/4 + 1; 3277c478bd9Sstevel@tonic-gate npk.n_bytes = (char *)remotekey; 3287c478bd9Sstevel@tonic-gate for (i = 0; i < keynum; i++) { 32961961e0fSrobinson if (key_encryptsession_pk(remotename, &npk, &deskey[i])) 3307c478bd9Sstevel@tonic-gate return (-1); 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate return (0); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 3357c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_len = remotekeylen/4 + 1; 3367c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_val = (char *)remotekey; 3377c478bd9Sstevel@tonic-gate arg.keylen = remotekeylen; 3387c478bd9Sstevel@tonic-gate arg.algtype = algtype; 3397c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_len = keynum; 3407c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_val = deskey; 34161961e0fSrobinson (void) memset(&res, 0, sizeof (res)); 3427c478bd9Sstevel@tonic-gate res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 3437c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_ENCRYPT_PK_3, 3447c478bd9Sstevel@tonic-gate xdr_cryptkeyarg3, (char *)&arg, 34561961e0fSrobinson xdr_cryptkeyres3, (char *)&res)) 3467c478bd9Sstevel@tonic-gate return (-1); 3477c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 3487c478bd9Sstevel@tonic-gate debug("encrypt3 status is nonzero"); 3497c478bd9Sstevel@tonic-gate return (-1); 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 3527c478bd9Sstevel@tonic-gate debug("number of keys don't match"); 3537c478bd9Sstevel@tonic-gate return (-1); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate return (0); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate int 35961961e0fSrobinson key_decryptsession_pk(const char *remotename, netobj *remotekey, 36061961e0fSrobinson des_block *deskey) 3617c478bd9Sstevel@tonic-gate { 3627c478bd9Sstevel@tonic-gate cryptkeyarg2 arg; 3637c478bd9Sstevel@tonic-gate cryptkeyres res; 3647c478bd9Sstevel@tonic-gate 36561961e0fSrobinson arg.remotename = (char *)remotename; 3667c478bd9Sstevel@tonic-gate arg.remotekey = *remotekey; 3677c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 3687c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, 36961961e0fSrobinson xdr_cryptkeyres, (char *)&res)) 3707c478bd9Sstevel@tonic-gate return (-1); 3717c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 3727c478bd9Sstevel@tonic-gate debug("decrypt status is nonzero"); 3737c478bd9Sstevel@tonic-gate return (-1); 3747c478bd9Sstevel@tonic-gate } 3757c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 3767c478bd9Sstevel@tonic-gate return (0); 3777c478bd9Sstevel@tonic-gate } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate int 3807c478bd9Sstevel@tonic-gate key_decryptsession_pk_g( 3817c478bd9Sstevel@tonic-gate const char *remotename, 3827c478bd9Sstevel@tonic-gate const char *remotekey, 3837c478bd9Sstevel@tonic-gate keylen_t remotekeylen, 3847c478bd9Sstevel@tonic-gate algtype_t algtype, 3857c478bd9Sstevel@tonic-gate des_block deskey[], 3867c478bd9Sstevel@tonic-gate keynum_t keynum 3877c478bd9Sstevel@tonic-gate ) 3887c478bd9Sstevel@tonic-gate { 3897c478bd9Sstevel@tonic-gate cryptkeyarg3 arg; 3907c478bd9Sstevel@tonic-gate cryptkeyres3 res; 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate if (CLASSIC_PK_DH(remotekeylen, algtype)) { 3937c478bd9Sstevel@tonic-gate int i; 3947c478bd9Sstevel@tonic-gate netobj npk; 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate npk.n_len = remotekeylen/4 + 1; 3977c478bd9Sstevel@tonic-gate npk.n_bytes = (char *)remotekey; 3987c478bd9Sstevel@tonic-gate for (i = 0; i < keynum; i++) { 39961961e0fSrobinson if (key_decryptsession_pk(remotename, 4007c478bd9Sstevel@tonic-gate &npk, &deskey[i])) 4017c478bd9Sstevel@tonic-gate return (-1); 4027c478bd9Sstevel@tonic-gate } 4037c478bd9Sstevel@tonic-gate return (0); 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 4067c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_len = remotekeylen/4 + 1; 4077c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_val = (char *)remotekey; 4087c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_len = keynum; 4097c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_val = deskey; 4107c478bd9Sstevel@tonic-gate arg.algtype = algtype; 4117c478bd9Sstevel@tonic-gate arg.keylen = remotekeylen; 41261961e0fSrobinson (void) memset(&res, 0, sizeof (res)); 4137c478bd9Sstevel@tonic-gate res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 4147c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_DECRYPT_PK_3, 4157c478bd9Sstevel@tonic-gate xdr_cryptkeyarg3, (char *)&arg, 41661961e0fSrobinson xdr_cryptkeyres3, (char *)&res)) 4177c478bd9Sstevel@tonic-gate return (-1); 4187c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 4197c478bd9Sstevel@tonic-gate debug("decrypt3 status is nonzero"); 4207c478bd9Sstevel@tonic-gate return (-1); 4217c478bd9Sstevel@tonic-gate } 4227c478bd9Sstevel@tonic-gate if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 4237c478bd9Sstevel@tonic-gate debug("number of keys don't match"); 4247c478bd9Sstevel@tonic-gate return (-1); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate return (0); 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate int 43061961e0fSrobinson key_encryptsession(const char *remotename, des_block *deskey) 4317c478bd9Sstevel@tonic-gate { 4327c478bd9Sstevel@tonic-gate cryptkeyarg arg; 4337c478bd9Sstevel@tonic-gate cryptkeyres res; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 4367c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 4377c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, 43861961e0fSrobinson xdr_cryptkeyres, (char *)&res)) 4397c478bd9Sstevel@tonic-gate return (-1); 4407c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 4417c478bd9Sstevel@tonic-gate debug("encrypt status is nonzero"); 4427c478bd9Sstevel@tonic-gate return (-1); 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 4457c478bd9Sstevel@tonic-gate return (0); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate int 4497c478bd9Sstevel@tonic-gate key_encryptsession_g( 4507c478bd9Sstevel@tonic-gate const char *remotename, 4517c478bd9Sstevel@tonic-gate keylen_t keylen, 4527c478bd9Sstevel@tonic-gate algtype_t algtype, 4537c478bd9Sstevel@tonic-gate des_block deskey[], 4547c478bd9Sstevel@tonic-gate keynum_t keynum 4557c478bd9Sstevel@tonic-gate ) 4567c478bd9Sstevel@tonic-gate { 4577c478bd9Sstevel@tonic-gate cryptkeyarg3 arg; 4587c478bd9Sstevel@tonic-gate cryptkeyres3 res; 4597c478bd9Sstevel@tonic-gate 46061961e0fSrobinson if (CLASSIC_PK_DH(keylen, algtype)) 4617c478bd9Sstevel@tonic-gate return (key_encryptsession(remotename, deskey)); 4627c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 4637c478bd9Sstevel@tonic-gate arg.algtype = algtype; 4647c478bd9Sstevel@tonic-gate arg.keylen = keylen; 4657c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_len = keynum; 4667c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_val = deskey; 4677c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_len = 0; 46861961e0fSrobinson (void) memset(&res, 0, sizeof (res)); 4697c478bd9Sstevel@tonic-gate res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 4707c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_ENCRYPT_3, xdr_cryptkeyarg3, (char *)&arg, 47161961e0fSrobinson xdr_cryptkeyres3, (char *)&res)) 4727c478bd9Sstevel@tonic-gate return (-1); 4737c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 4747c478bd9Sstevel@tonic-gate debug("encrypt3 status is nonzero"); 4757c478bd9Sstevel@tonic-gate return (-1); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 4787c478bd9Sstevel@tonic-gate debug("encrypt3 didn't return same number of keys"); 4797c478bd9Sstevel@tonic-gate return (-1); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate return (0); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate int 48661961e0fSrobinson key_decryptsession(const char *remotename, des_block *deskey) 4877c478bd9Sstevel@tonic-gate { 4887c478bd9Sstevel@tonic-gate cryptkeyarg arg; 4897c478bd9Sstevel@tonic-gate cryptkeyres res; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 4927c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 4937c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, 49461961e0fSrobinson xdr_cryptkeyres, (char *)&res)) 4957c478bd9Sstevel@tonic-gate return (-1); 4967c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 4977c478bd9Sstevel@tonic-gate debug("decrypt status is nonzero"); 4987c478bd9Sstevel@tonic-gate return (-1); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 5017c478bd9Sstevel@tonic-gate return (0); 5027c478bd9Sstevel@tonic-gate } 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate int 5057c478bd9Sstevel@tonic-gate key_decryptsession_g( 5067c478bd9Sstevel@tonic-gate const char *remotename, 5077c478bd9Sstevel@tonic-gate keylen_t keylen, 5087c478bd9Sstevel@tonic-gate algtype_t algtype, 5097c478bd9Sstevel@tonic-gate des_block deskey[], 5107c478bd9Sstevel@tonic-gate keynum_t keynum 5117c478bd9Sstevel@tonic-gate ) 5127c478bd9Sstevel@tonic-gate { 5137c478bd9Sstevel@tonic-gate cryptkeyarg3 arg; 5147c478bd9Sstevel@tonic-gate cryptkeyres3 res; 5157c478bd9Sstevel@tonic-gate 51661961e0fSrobinson if (CLASSIC_PK_DH(keylen, algtype)) 5177c478bd9Sstevel@tonic-gate return (key_decryptsession(remotename, deskey)); 5187c478bd9Sstevel@tonic-gate arg.remotename = (char *)remotename; 5197c478bd9Sstevel@tonic-gate arg.algtype = algtype; 5207c478bd9Sstevel@tonic-gate arg.keylen = keylen; 5217c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_len = keynum; 5227c478bd9Sstevel@tonic-gate arg.deskey.deskeyarray_val = deskey; 5237c478bd9Sstevel@tonic-gate arg.remotekey.keybuf3_len = 0; 52461961e0fSrobinson (void) memset(&res, 0, sizeof (res)); 5257c478bd9Sstevel@tonic-gate res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 5267c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_DECRYPT_3, xdr_cryptkeyarg3, (char *)&arg, 52761961e0fSrobinson xdr_cryptkeyres3, (char *)&res)) 5287c478bd9Sstevel@tonic-gate return (-1); 5297c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 5307c478bd9Sstevel@tonic-gate debug("decrypt3 status is nonzero"); 5317c478bd9Sstevel@tonic-gate return (-1); 5327c478bd9Sstevel@tonic-gate } 5337c478bd9Sstevel@tonic-gate if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 5347c478bd9Sstevel@tonic-gate debug("decrypt3 didn't return same number of keys"); 5357c478bd9Sstevel@tonic-gate return (-1); 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate return (0); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate int 54161961e0fSrobinson key_gendes(des_block *key) 5427c478bd9Sstevel@tonic-gate { 54361961e0fSrobinson if (!key_call((rpcproc_t)KEY_GEN, xdr_void, NULL, 54461961e0fSrobinson xdr_des_block, (char *)key)) 5457c478bd9Sstevel@tonic-gate return (-1); 5467c478bd9Sstevel@tonic-gate return (0); 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate int 5507c478bd9Sstevel@tonic-gate key_gendes_g( 5517c478bd9Sstevel@tonic-gate des_block deskey[], 5527c478bd9Sstevel@tonic-gate keynum_t keynum 5537c478bd9Sstevel@tonic-gate ) 5547c478bd9Sstevel@tonic-gate { 5557c478bd9Sstevel@tonic-gate deskeyarray res; 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate res.deskeyarray_val = deskey; 5587c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_GEN_3, xdr_keynum_t, (char *)&keynum, 55961961e0fSrobinson xdr_deskeyarray, (char *)&res)) 5607c478bd9Sstevel@tonic-gate return (-1); 5617c478bd9Sstevel@tonic-gate if (res.deskeyarray_len != keynum) { 5627c478bd9Sstevel@tonic-gate debug("return length doesn't match\n"); 5637c478bd9Sstevel@tonic-gate return (-1); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate return (0); 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * Call KEY_NET_PUT Operation to the keyserv. 5707c478bd9Sstevel@tonic-gate * 5717c478bd9Sstevel@tonic-gate * If use_ruid == 0, use effective uid. 5727c478bd9Sstevel@tonic-gate * If use_ruid == 1, use real uid. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate int 5757c478bd9Sstevel@tonic-gate key_setnet_ext(struct key_netstarg *arg, int use_ruid) 5767c478bd9Sstevel@tonic-gate { 5777c478bd9Sstevel@tonic-gate keystatus status; 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate if (!key_call_ext((rpcproc_t)KEY_NET_PUT, xdr_key_netstarg, 58061961e0fSrobinson (char *)arg, xdr_keystatus, (char *)&status, use_ruid)) 5817c478bd9Sstevel@tonic-gate return (-1); 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate if (status != KEY_SUCCESS) { 5847c478bd9Sstevel@tonic-gate debug("key_setnet status is nonzero"); 5857c478bd9Sstevel@tonic-gate return (-1); 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate return (1); 5887c478bd9Sstevel@tonic-gate } 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* 5917c478bd9Sstevel@tonic-gate * Use effective uid. 5927c478bd9Sstevel@tonic-gate */ 5937c478bd9Sstevel@tonic-gate int 5947c478bd9Sstevel@tonic-gate key_setnet(struct key_netstarg *arg) 5957c478bd9Sstevel@tonic-gate { 5967c478bd9Sstevel@tonic-gate return (key_setnet_ext(arg, 0)); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* 6007c478bd9Sstevel@tonic-gate * Use real uid. 6017c478bd9Sstevel@tonic-gate */ 6027c478bd9Sstevel@tonic-gate int 6037c478bd9Sstevel@tonic-gate key_setnet_ruid(struct key_netstarg *arg) 6047c478bd9Sstevel@tonic-gate { 6057c478bd9Sstevel@tonic-gate return (key_setnet_ext(arg, 1)); 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate /* 6097c478bd9Sstevel@tonic-gate * Input netname, secret and public keys (hex string representation) 6107c478bd9Sstevel@tonic-gate * of length skeylen/pkeylen (bits), and algorithm type. One, but not 6117c478bd9Sstevel@tonic-gate * both, of skey or pkey may have zero length. If both lengths are 6127c478bd9Sstevel@tonic-gate * specified, they must be the same. 6137c478bd9Sstevel@tonic-gate * 6147c478bd9Sstevel@tonic-gate * Call KEY_NET_PUT_3 Operation to the keyserv. 6157c478bd9Sstevel@tonic-gate * Stores the specified netname/pkey/skey triplet in the keyserv. 6167c478bd9Sstevel@tonic-gate * 6177c478bd9Sstevel@tonic-gate * If (use_ruid == 1), use real uid. 6187c478bd9Sstevel@tonic-gate * If (use_ruid == 0), use effective uid. 6197c478bd9Sstevel@tonic-gate */ 6207c478bd9Sstevel@tonic-gate int 6217c478bd9Sstevel@tonic-gate key_setnet_g_ext( 6227c478bd9Sstevel@tonic-gate const char *netname, 6237c478bd9Sstevel@tonic-gate const char *skey, 6247c478bd9Sstevel@tonic-gate keylen_t skeylen, 6257c478bd9Sstevel@tonic-gate const char *pkey, 6267c478bd9Sstevel@tonic-gate keylen_t pkeylen, 6277c478bd9Sstevel@tonic-gate algtype_t algtype, 6287c478bd9Sstevel@tonic-gate int use_ruid) 6297c478bd9Sstevel@tonic-gate { 6307c478bd9Sstevel@tonic-gate key_netstarg3 arg; 6317c478bd9Sstevel@tonic-gate keystatus status; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate arg.st_netname = (char *)netname; 6347c478bd9Sstevel@tonic-gate arg.algtype = algtype; 6357c478bd9Sstevel@tonic-gate if (skeylen == 0) { 6367c478bd9Sstevel@tonic-gate arg.st_priv_key.keybuf3_len = 0; 6377c478bd9Sstevel@tonic-gate } else { 6387c478bd9Sstevel@tonic-gate arg.st_priv_key.keybuf3_len = skeylen/4 + 1; 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate arg.st_priv_key.keybuf3_val = (char *)skey; 6417c478bd9Sstevel@tonic-gate if (pkeylen == 0) { 6427c478bd9Sstevel@tonic-gate arg.st_pub_key.keybuf3_len = 0; 6437c478bd9Sstevel@tonic-gate } else { 6447c478bd9Sstevel@tonic-gate arg.st_pub_key.keybuf3_len = pkeylen/4 + 1; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate arg.st_pub_key.keybuf3_val = (char *)pkey; 6477c478bd9Sstevel@tonic-gate if (skeylen == 0) { 6487c478bd9Sstevel@tonic-gate if (pkeylen == 0) { 6497c478bd9Sstevel@tonic-gate debug("keylens are both 0"); 6507c478bd9Sstevel@tonic-gate return (-1); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate arg.keylen = pkeylen; 6537c478bd9Sstevel@tonic-gate } else { 6547c478bd9Sstevel@tonic-gate if ((pkeylen != 0) && (skeylen != pkeylen)) { 6557c478bd9Sstevel@tonic-gate debug("keylens don't match"); 6567c478bd9Sstevel@tonic-gate return (-1); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate arg.keylen = skeylen; 6597c478bd9Sstevel@tonic-gate } 6607c478bd9Sstevel@tonic-gate if (CLASSIC_PK_DH(arg.keylen, arg.algtype)) { 6617c478bd9Sstevel@tonic-gate key_netstarg tmp; 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (skeylen != 0) { 66461961e0fSrobinson (void) memcpy(&tmp.st_priv_key, skey, 6657c478bd9Sstevel@tonic-gate sizeof (tmp.st_priv_key)); 6667c478bd9Sstevel@tonic-gate } else { 66761961e0fSrobinson (void) memset(&tmp.st_priv_key, 0, 66861961e0fSrobinson sizeof (tmp.st_priv_key)); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate if (pkeylen != 0) { 67161961e0fSrobinson (void) memcpy(&tmp.st_pub_key, skey, 67261961e0fSrobinson sizeof (tmp.st_pub_key)); 6737c478bd9Sstevel@tonic-gate } else { 67461961e0fSrobinson (void) memset(&tmp.st_pub_key, 0, 67561961e0fSrobinson sizeof (tmp.st_pub_key)); 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate tmp.st_netname = (char *)netname; 6787c478bd9Sstevel@tonic-gate return (key_setnet(&tmp)); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate if (!key_call_ext((rpcproc_t)KEY_NET_PUT_3, 6817c478bd9Sstevel@tonic-gate xdr_key_netstarg3, (char *)&arg, 6827c478bd9Sstevel@tonic-gate xdr_keystatus, (char *)&status, use_ruid)) { 6837c478bd9Sstevel@tonic-gate return (-1); 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate if (status != KEY_SUCCESS) { 6877c478bd9Sstevel@tonic-gate debug("key_setnet3 status is nonzero"); 6887c478bd9Sstevel@tonic-gate return (-1); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate return (0); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* 6947c478bd9Sstevel@tonic-gate * Use effective uid. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate int 6977c478bd9Sstevel@tonic-gate key_setnet_g(const char *netname, const char *skey, keylen_t skeylen, 6987c478bd9Sstevel@tonic-gate const char *pkey, keylen_t pkeylen, algtype_t algtype) 6997c478bd9Sstevel@tonic-gate { 7007c478bd9Sstevel@tonic-gate return (key_setnet_g_ext(netname, skey, skeylen, pkey, pkeylen, 7017c478bd9Sstevel@tonic-gate algtype, 0)); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * Use real uid. 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate int 7087c478bd9Sstevel@tonic-gate key_setnet_g_ruid(const char *netname, const char *skey, keylen_t skeylen, 7097c478bd9Sstevel@tonic-gate const char *pkey, keylen_t pkeylen, algtype_t algtype) 7107c478bd9Sstevel@tonic-gate { 7117c478bd9Sstevel@tonic-gate return (key_setnet_g_ext(netname, skey, skeylen, pkey, pkeylen, 7127c478bd9Sstevel@tonic-gate algtype, 1)); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate int 71661961e0fSrobinson key_get_conv(char *pkey, des_block *deskey) 7177c478bd9Sstevel@tonic-gate { 7187c478bd9Sstevel@tonic-gate cryptkeyres res; 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_GET_CONV, xdr_keybuf, pkey, 72161961e0fSrobinson xdr_cryptkeyres, (char *)&res)) 7227c478bd9Sstevel@tonic-gate return (-1); 7237c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 7247c478bd9Sstevel@tonic-gate debug("get_conv status is nonzero"); 7257c478bd9Sstevel@tonic-gate return (-1); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 7287c478bd9Sstevel@tonic-gate return (0); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate int 7327c478bd9Sstevel@tonic-gate key_get_conv_g( 7337c478bd9Sstevel@tonic-gate const char *pkey, 7347c478bd9Sstevel@tonic-gate keylen_t pkeylen, 7357c478bd9Sstevel@tonic-gate algtype_t algtype, 7367c478bd9Sstevel@tonic-gate des_block deskey[], 7377c478bd9Sstevel@tonic-gate keynum_t keynum 7387c478bd9Sstevel@tonic-gate ) 7397c478bd9Sstevel@tonic-gate { 7407c478bd9Sstevel@tonic-gate deskeyarg3 arg; 7417c478bd9Sstevel@tonic-gate cryptkeyres3 res; 7427c478bd9Sstevel@tonic-gate 74361961e0fSrobinson if (CLASSIC_PK_DH(pkeylen, algtype)) 7447c478bd9Sstevel@tonic-gate return (key_get_conv((char *)pkey, deskey)); 7457c478bd9Sstevel@tonic-gate arg.pub_key.keybuf3_len = pkeylen/4 + 1; 7467c478bd9Sstevel@tonic-gate arg.pub_key.keybuf3_val = (char *)pkey; 7477c478bd9Sstevel@tonic-gate arg.nkeys = keynum; 7487c478bd9Sstevel@tonic-gate arg.algtype = algtype; 7497c478bd9Sstevel@tonic-gate arg.keylen = pkeylen; 75061961e0fSrobinson (void) memset(&res, 0, sizeof (res)); 7517c478bd9Sstevel@tonic-gate res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 7527c478bd9Sstevel@tonic-gate if (!key_call((rpcproc_t)KEY_GET_CONV_3, xdr_deskeyarg3, (char *)&arg, 75361961e0fSrobinson xdr_cryptkeyres3, (char *)&res)) 7547c478bd9Sstevel@tonic-gate return (-1); 7557c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 7567c478bd9Sstevel@tonic-gate debug("get_conv3 status is nonzero"); 7577c478bd9Sstevel@tonic-gate return (-1); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 7607c478bd9Sstevel@tonic-gate debug("get_conv3 number of keys dont match"); 7617c478bd9Sstevel@tonic-gate return (-1); 7627c478bd9Sstevel@tonic-gate } 7637c478bd9Sstevel@tonic-gate return (0); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate struct key_call_private { 7677c478bd9Sstevel@tonic-gate CLIENT *client; /* Client handle */ 7687c478bd9Sstevel@tonic-gate pid_t pid; /* process-id at moment of creation */ 7697c478bd9Sstevel@tonic-gate int fd; /* client handle fd */ 7707c478bd9Sstevel@tonic-gate dev_t rdev; /* device client handle is using */ 7717c478bd9Sstevel@tonic-gate }; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate static void set_rdev(struct key_call_private *); 7747c478bd9Sstevel@tonic-gate static int check_rdev(struct key_call_private *); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate static void 7777c478bd9Sstevel@tonic-gate key_call_destroy(void *vp) 7787c478bd9Sstevel@tonic-gate { 7797c478bd9Sstevel@tonic-gate struct key_call_private *kcp = (struct key_call_private *)vp; 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate if (kcp != NULL && kcp->client != NULL) { 78261961e0fSrobinson (void) check_rdev(kcp); 7837c478bd9Sstevel@tonic-gate clnt_destroy(kcp->client); 7847c478bd9Sstevel@tonic-gate free(kcp); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate } 7877c478bd9Sstevel@tonic-gate 788*cb620785Sraf static pthread_key_t key_call_key = PTHREAD_ONCE_KEY_NP; 7897c478bd9Sstevel@tonic-gate 7907c478bd9Sstevel@tonic-gate void 7917c478bd9Sstevel@tonic-gate _key_call_fini(void) 7927c478bd9Sstevel@tonic-gate { 793*cb620785Sraf struct key_call_private *kcp; 7947c478bd9Sstevel@tonic-gate 795*cb620785Sraf if ((kcp = pthread_getspecific(key_call_key)) != NULL) { 7967c478bd9Sstevel@tonic-gate key_call_destroy(kcp); 7977c478bd9Sstevel@tonic-gate (void) pthread_setspecific(key_call_key, NULL); 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Keep the handle cached. This call may be made quite often. 8037c478bd9Sstevel@tonic-gate */ 8047c478bd9Sstevel@tonic-gate static CLIENT * 8057c478bd9Sstevel@tonic-gate getkeyserv_handle(int vers, int stale) 8067c478bd9Sstevel@tonic-gate { 8077c478bd9Sstevel@tonic-gate struct key_call_private *kcp = NULL; 8087c478bd9Sstevel@tonic-gate int _update_did(); 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate kcp = thr_get_storage(&key_call_key, sizeof (*kcp), key_call_destroy); 8117c478bd9Sstevel@tonic-gate if (kcp == NULL) { 8127c478bd9Sstevel@tonic-gate syslog(LOG_CRIT, "getkeyserv_handle: out of memory"); 8137c478bd9Sstevel@tonic-gate return (NULL); 8147c478bd9Sstevel@tonic-gate } 8157c478bd9Sstevel@tonic-gate 8167c478bd9Sstevel@tonic-gate /* 8177c478bd9Sstevel@tonic-gate * if pid has changed, destroy client and rebuild 8187c478bd9Sstevel@tonic-gate * or if stale is '1' then destroy client and rebuild 8197c478bd9Sstevel@tonic-gate */ 8207c478bd9Sstevel@tonic-gate if (kcp->client && 8217c478bd9Sstevel@tonic-gate (!check_rdev(kcp) || kcp->pid != getpid() || stale)) { 8227c478bd9Sstevel@tonic-gate clnt_destroy(kcp->client); 8237c478bd9Sstevel@tonic-gate kcp->client = NULL; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate if (kcp->client) { 8267c478bd9Sstevel@tonic-gate int fd; 8277c478bd9Sstevel@tonic-gate /* 8287c478bd9Sstevel@tonic-gate * Change the version number to the new one. 8297c478bd9Sstevel@tonic-gate */ 8307c478bd9Sstevel@tonic-gate clnt_control(kcp->client, CLSET_VERS, (void *)&vers); 8317c478bd9Sstevel@tonic-gate if (!_update_did(kcp->client, vers)) { 8327c478bd9Sstevel@tonic-gate if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) 8337c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "getkeyserv_handle: " 8347c478bd9Sstevel@tonic-gate "out of memory!"); 8357c478bd9Sstevel@tonic-gate return (NULL); 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate /* Update fd in kcp because it was reopened in _update_did */ 8387c478bd9Sstevel@tonic-gate if (clnt_control(kcp->client, CLGET_FD, (void *)&fd) && 8397c478bd9Sstevel@tonic-gate (fd >= 0)) 840e8031f0aSraf (void) fcntl(fd, F_SETFD, FD_CLOEXEC); /* close exec */ 8417c478bd9Sstevel@tonic-gate kcp->fd = fd; 8427c478bd9Sstevel@tonic-gate return (kcp->client); 8437c478bd9Sstevel@tonic-gate } 8447c478bd9Sstevel@tonic-gate 8457c478bd9Sstevel@tonic-gate if ((kcp->client = clnt_door_create(KEY_PROG, vers, 0)) == NULL) 8467c478bd9Sstevel@tonic-gate return (NULL); 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate kcp->pid = getpid(); 8497c478bd9Sstevel@tonic-gate set_rdev(kcp); 850e8031f0aSraf (void) fcntl(kcp->fd, F_SETFD, FD_CLOEXEC); /* close on exec */ 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate return (kcp->client); 8537c478bd9Sstevel@tonic-gate } 8547c478bd9Sstevel@tonic-gate 8557c478bd9Sstevel@tonic-gate /* 8567c478bd9Sstevel@tonic-gate * RPC calls to the keyserv. 8577c478bd9Sstevel@tonic-gate * 8587c478bd9Sstevel@tonic-gate * If (use_ruid == 1), use real uid. 8597c478bd9Sstevel@tonic-gate * If (use_ruid == 0), use effective uid. 8607c478bd9Sstevel@tonic-gate * Returns 0 on failure, 1 on success 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate int 86361961e0fSrobinson key_call_ext(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, 86461961e0fSrobinson char *rslt, int use_ruid) 8657c478bd9Sstevel@tonic-gate { 8667c478bd9Sstevel@tonic-gate CLIENT *clnt; 8677c478bd9Sstevel@tonic-gate struct timeval wait_time = {0, 0}; 8687c478bd9Sstevel@tonic-gate enum clnt_stat status; 8697c478bd9Sstevel@tonic-gate int vers; 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { 8727c478bd9Sstevel@tonic-gate cryptkeyres res; 8737c478bd9Sstevel@tonic-gate bool_t r; 8747c478bd9Sstevel@tonic-gate r = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg, &res); 8757c478bd9Sstevel@tonic-gate if (r == TRUE) { 8767c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 8777c478bd9Sstevel@tonic-gate *(cryptkeyres*)rslt = res; 8787c478bd9Sstevel@tonic-gate return (1); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate return (0); 8817c478bd9Sstevel@tonic-gate } 8827c478bd9Sstevel@tonic-gate if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { 8837c478bd9Sstevel@tonic-gate cryptkeyres res; 8847c478bd9Sstevel@tonic-gate bool_t r; 8857c478bd9Sstevel@tonic-gate r = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg, &res); 8867c478bd9Sstevel@tonic-gate if (r == TRUE) { 8877c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 8887c478bd9Sstevel@tonic-gate *(cryptkeyres*)rslt = res; 8897c478bd9Sstevel@tonic-gate return (1); 8907c478bd9Sstevel@tonic-gate } 8917c478bd9Sstevel@tonic-gate return (0); 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate if (proc == KEY_GEN && __key_gendes_LOCAL) { 8947c478bd9Sstevel@tonic-gate des_block res; 8957c478bd9Sstevel@tonic-gate bool_t r; 8967c478bd9Sstevel@tonic-gate r = (*__key_gendes_LOCAL)(geteuid(), 0, &res); 8977c478bd9Sstevel@tonic-gate if (r == TRUE) { 8987c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */ 8997c478bd9Sstevel@tonic-gate *(des_block*)rslt = res; 9007c478bd9Sstevel@tonic-gate return (1); 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate return (0); 9037c478bd9Sstevel@tonic-gate } 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || 9067c478bd9Sstevel@tonic-gate (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || 9077c478bd9Sstevel@tonic-gate (proc == KEY_GET_CONV)) 9087c478bd9Sstevel@tonic-gate vers = 2; /* talk to version 2 */ 9097c478bd9Sstevel@tonic-gate else 9107c478bd9Sstevel@tonic-gate vers = 1; /* talk to version 1 */ 9117c478bd9Sstevel@tonic-gate 9127c478bd9Sstevel@tonic-gate clnt = getkeyserv_handle(vers, 0); 9137c478bd9Sstevel@tonic-gate if (clnt == NULL) 9147c478bd9Sstevel@tonic-gate return (0); 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate auth_destroy(clnt->cl_auth); 9177c478bd9Sstevel@tonic-gate if (use_ruid) 9187c478bd9Sstevel@tonic-gate clnt->cl_auth = authsys_create_ruid(); 9197c478bd9Sstevel@tonic-gate else 9207c478bd9Sstevel@tonic-gate clnt->cl_auth = authnone_create(); 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate status = CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt, 9237c478bd9Sstevel@tonic-gate rslt, wait_time); 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate switch (status) { 9267c478bd9Sstevel@tonic-gate case RPC_SUCCESS: 9277c478bd9Sstevel@tonic-gate return (1); 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate case RPC_CANTRECV: 9307c478bd9Sstevel@tonic-gate /* 9317c478bd9Sstevel@tonic-gate * keyserv was probably restarted, so we'll try once more 9327c478bd9Sstevel@tonic-gate */ 9337c478bd9Sstevel@tonic-gate if ((clnt = getkeyserv_handle(vers, 1)) == NULL) 9347c478bd9Sstevel@tonic-gate return (0); 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate auth_destroy(clnt->cl_auth); 9377c478bd9Sstevel@tonic-gate if (use_ruid) 9387c478bd9Sstevel@tonic-gate clnt->cl_auth = authsys_create_ruid(); 9397c478bd9Sstevel@tonic-gate else 9407c478bd9Sstevel@tonic-gate clnt->cl_auth = authnone_create(); 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate 9437c478bd9Sstevel@tonic-gate if (CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, 9447c478bd9Sstevel@tonic-gate wait_time) == RPC_SUCCESS) 9457c478bd9Sstevel@tonic-gate return (1); 9467c478bd9Sstevel@tonic-gate return (0); 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate default: 9497c478bd9Sstevel@tonic-gate return (0); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate /* 9547c478bd9Sstevel@tonic-gate * Use effective uid. 9557c478bd9Sstevel@tonic-gate */ 9567c478bd9Sstevel@tonic-gate int 9577c478bd9Sstevel@tonic-gate key_call(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, 9587c478bd9Sstevel@tonic-gate char *rslt) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate return (key_call_ext(proc, xdr_arg, arg, xdr_rslt, rslt, 0)); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 9637c478bd9Sstevel@tonic-gate /* 9647c478bd9Sstevel@tonic-gate * Use real uid. 9657c478bd9Sstevel@tonic-gate */ 9667c478bd9Sstevel@tonic-gate int 9677c478bd9Sstevel@tonic-gate key_call_ruid(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, 9687c478bd9Sstevel@tonic-gate xdrproc_t xdr_rslt, char *rslt) 9697c478bd9Sstevel@tonic-gate { 9707c478bd9Sstevel@tonic-gate return (key_call_ext(proc, xdr_arg, arg, xdr_rslt, rslt, 1)); 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 97361961e0fSrobinson static void 97461961e0fSrobinson set_rdev(struct key_call_private *kcp) 9757c478bd9Sstevel@tonic-gate { 9767c478bd9Sstevel@tonic-gate int fd; 9777c478bd9Sstevel@tonic-gate struct stat stbuf; 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate if (clnt_control(kcp->client, CLGET_FD, (char *)&fd) != TRUE || 980e8031f0aSraf fstat(fd, &stbuf) == -1) { 9817c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "keyserv_client: can't get info"); 9827c478bd9Sstevel@tonic-gate kcp->fd = -1; 9837c478bd9Sstevel@tonic-gate return; 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate kcp->fd = fd; 9867c478bd9Sstevel@tonic-gate kcp->rdev = stbuf.st_rdev; 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 98961961e0fSrobinson static int 99061961e0fSrobinson check_rdev(struct key_call_private *kcp) 9917c478bd9Sstevel@tonic-gate { 9927c478bd9Sstevel@tonic-gate struct stat stbuf; 9937c478bd9Sstevel@tonic-gate 9947c478bd9Sstevel@tonic-gate if (kcp->fd == -1) 9957c478bd9Sstevel@tonic-gate return (1); /* can't check it, assume it is okay */ 9967c478bd9Sstevel@tonic-gate 997e8031f0aSraf if (fstat(kcp->fd, &stbuf) == -1) { 9987c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "keyserv_client: can't stat %d", kcp->fd); 9997c478bd9Sstevel@tonic-gate /* could be because file descriptor was closed */ 10007c478bd9Sstevel@tonic-gate /* it's not our file descriptor, so don't try to close it */ 100161961e0fSrobinson clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate return (0); 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate if (kcp->rdev != stbuf.st_rdev) { 10067c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 10077c478bd9Sstevel@tonic-gate "keyserv_client: fd %d changed, old=0x%x, new=0x%x", 10087c478bd9Sstevel@tonic-gate kcp->fd, kcp->rdev, stbuf.st_rdev); 10097c478bd9Sstevel@tonic-gate /* it's not our file descriptor, so don't try to close it */ 101061961e0fSrobinson clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL); 10117c478bd9Sstevel@tonic-gate return (0); 10127c478bd9Sstevel@tonic-gate } 10137c478bd9Sstevel@tonic-gate return (1); /* fd is okay */ 10147c478bd9Sstevel@tonic-gate } 1015