4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
32 #include <rpc/key_prot.h>
33 #include <rpcsvc/nis_dhext.h>
37 /* defined in usr/src/libnsl/rpc/key_call.c */
38 extern bool_t (*__key_encryptsession_pk_LOCAL
)();
39 extern bool_t (*__key_decryptsession_pk_LOCAL
)();
40 extern bool_t (*__key_gendes_LOCAL
)();
42 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0))
45 * authsys_create_uid(uid_t uid)
47 * Create SYS (UNIX) style authenticator for the given uid/gid
48 * We don't include suplementary groups, since these are of no
49 * interest for the keyserv operations that we do.
52 authsys_create_uid(uid_t uid
, gid_t gid
)
54 char host
[MAX_MACHINE_NAME
+ 1];
57 if (gethostname(host
, sizeof (host
) - 1) == -1) {
59 "pam_dhkeys: Can't determine hostname: %m");
62 host
[MAX_MACHINE_NAME
] = '\0';
64 res
= authsys_create(host
, uid
, gid
, 0, (gid_t
*)NULL
);
70 * my_key_call(proc, xdr_arg, arg, xdr_rslt, rslt, uit, gid)
72 * my_key_call is a copy of key_call() from libnsl with the
73 * added AUTHSYS rpc credential to make the keyserver use our
74 * REAL UID instead of our EFFECTIVE UID when handling our keys.
77 my_key_call(rpcproc_t proc
, xdrproc_t xdr_arg
, char *arg
,
78 xdrproc_t xdr_rslt
, char *rslt
, uid_t uid
, gid_t gid
)
81 struct timeval wait_time
= {0, 0};
82 enum clnt_stat status
;
85 if (proc
== KEY_ENCRYPT_PK
&& __key_encryptsession_pk_LOCAL
) {
88 r
= (*__key_encryptsession_pk_LOCAL
)(uid
, arg
, &res
);
90 /* LINTED pointer alignment */
91 *(cryptkeyres
*)rslt
= res
;
96 if (proc
== KEY_DECRYPT_PK
&& __key_decryptsession_pk_LOCAL
) {
99 r
= (*__key_decryptsession_pk_LOCAL
)(uid
, arg
, &res
);
101 /* LINTED pointer alignment */
102 *(cryptkeyres
*)rslt
= res
;
107 if (proc
== KEY_GEN
&& __key_gendes_LOCAL
) {
110 r
= (*__key_gendes_LOCAL
)(uid
, 0, &res
);
112 /* LINTED pointer alignment */
113 *(des_block
*)rslt
= res
;
119 if ((proc
== KEY_ENCRYPT_PK
) || (proc
== KEY_DECRYPT_PK
) ||
120 (proc
== KEY_NET_GET
) || (proc
== KEY_NET_PUT
) ||
121 (proc
== KEY_GET_CONV
))
122 vers
= 2; /* talk to version 2 */
124 vers
= 1; /* talk to version 1 */
126 clnt
= clnt_door_create(KEY_PROG
, vers
, 0);
131 clnt
->cl_auth
= authsys_create_uid(uid
, gid
);
133 status
= CLNT_CALL(clnt
, proc
, xdr_arg
, arg
, xdr_rslt
,
136 auth_destroy(clnt
->cl_auth
);
139 return (status
== RPC_SUCCESS
? 1 : 0);
143 key_setnet_uid(struct key_netstarg
*arg
, uid_t uid
, gid_t gid
)
147 if (!my_key_call((rpcproc_t
)KEY_NET_PUT
, xdr_key_netstarg
,
148 (char *)arg
, xdr_keystatus
, (char *)&status
, uid
, gid
)) {
151 if (status
!= KEY_SUCCESS
) {
159 key_setnet_g_uid(const char *netname
, const char *skey
, keylen_t skeylen
,
160 const char *pkey
, keylen_t pkeylen
, algtype_t algtype
,
161 uid_t uid
, gid_t gid
)
166 arg
.st_netname
= (char *)netname
;
167 arg
.algtype
= algtype
;
170 arg
.st_priv_key
.keybuf3_len
= 0;
172 arg
.st_priv_key
.keybuf3_len
= skeylen
/4 + 1;
174 arg
.st_priv_key
.keybuf3_val
= (char *)skey
;
177 arg
.st_pub_key
.keybuf3_len
= 0;
179 arg
.st_pub_key
.keybuf3_len
= pkeylen
/4 + 1;
181 arg
.st_pub_key
.keybuf3_val
= (char *)pkey
;
185 /* debug("keylens are both 0"); */
188 arg
.keylen
= pkeylen
;
190 if ((pkeylen
!= 0) && (skeylen
!= pkeylen
)) {
191 /* debug("keylens don't match"); */
194 arg
.keylen
= skeylen
;
197 if (CLASSIC_PK_DH(arg
.keylen
, arg
.algtype
)) {
201 (void) memcpy(&tmp
.st_priv_key
, skey
,
202 sizeof (tmp
.st_priv_key
));
204 (void) memset(&tmp
.st_priv_key
, 0,
205 sizeof (tmp
.st_priv_key
));
208 (void) memcpy(&tmp
.st_pub_key
, skey
,
209 sizeof (tmp
.st_pub_key
));
211 (void) memset(&tmp
.st_pub_key
, 0,
212 sizeof (tmp
.st_pub_key
));
214 tmp
.st_netname
= (char *)netname
;
215 return (key_setnet_uid(&tmp
, uid
, gid
));
218 if (!my_key_call((rpcproc_t
)KEY_NET_PUT_3
, xdr_key_netstarg3
,
219 (char *)&arg
, xdr_keystatus
, (char *)&status
, uid
, gid
)) {
223 if (status
!= KEY_SUCCESS
) {
224 /* debug("key_setnet3 status is nonzero"); */
232 * key_secretkey_is_set_uid() returns 1 if the keyserver has a secret key
233 * stored for the caller's REAL uid; it returns 0 otherwise
236 key_secretkey_is_set_uid(uid_t uid
, gid_t gid
)
238 struct key_netstres kres
;
240 (void) memset((void*)&kres
, 0, sizeof (kres
));
242 if (my_key_call((rpcproc_t
)KEY_NET_GET
, xdr_void
, (char *)NULL
,
243 xdr_key_netstres
, (char *)&kres
, uid
, gid
) &&
244 (kres
.status
== KEY_SUCCESS
) &&
245 (kres
.key_netstres_u
.knet
.st_priv_key
[0] != 0)) {
246 /* avoid leaving secret key in memory */
247 (void) memset(kres
.key_netstres_u
.knet
.st_priv_key
, 0,
249 xdr_free(xdr_key_netstres
, (char *)&kres
);
256 key_removesecret_g_uid(uid_t uid
, gid_t gid
)
260 if (my_key_call((rpcproc_t
)KEY_CLEAR_3
, xdr_void
, (char *)NULL
,
261 xdr_keystatus
, (char *)&status
, uid
, gid
))
264 if (status
!= KEY_SUCCESS
)