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]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include <sys/types.h>
38 #include <gssapi/gssapi.h>
39 #include <gssapi/gssapi_ext.h>
41 #include <rpc/rpcsec_defs.h>
43 #define SVC_INTEGRITY "integrity"
44 #define SVC_PRIVACY "privacy"
45 #define SVC_NONE "none"
46 #define SVC_DEFAULT "default"
48 #define MCALL_MSG_SIZE 24
50 * Private data kept per client handle
53 int cu_fd
; /* connections fd */
54 bool_t cu_closeit
; /* opened by library */
55 struct netbuf cu_raddr
; /* remote address */
56 struct timeval cu_wait
; /* retransmit interval */
57 struct timeval cu_total
; /* total time for the call */
58 struct rpc_err cu_error
;
59 struct t_unitdata
*cu_tr_data
;
61 char *cu_outbuf_start
;
62 char cu_outbuf
[MCALL_MSG_SIZE
];
64 uint_t cu_sendsz
; /* send size */
65 uint_t cu_recvsz
; /* recv size */
71 * Internal utility routines.
74 __rpc_gss_mech_to_oid(char *mech
, rpc_gss_OID
*oid
)
76 if (__gss_mech_to_oid(mech
, (gss_OID
*)oid
) != GSS_S_COMPLETE
)
82 __rpc_gss_oid_to_mech(rpc_gss_OID oid
)
84 return ((char *)__gss_oid_to_mech((const gss_OID
)oid
));
89 __rpc_gss_qop_to_num(char *qop
, char *mech
, OM_uint32
*num
)
91 if (__gss_qop_to_num(qop
, mech
, num
) != GSS_S_COMPLETE
)
97 __rpc_gss_num_to_qop(char *mech
, OM_uint32 num
)
101 if (__gss_num_to_qop(mech
, num
, &qop
) != GSS_S_COMPLETE
)
107 __rpc_gss_svc_to_num(char *svc
, rpc_gss_service_t
*num
)
109 if (strcasecmp(svc
, SVC_INTEGRITY
) == 0)
110 *num
= rpc_gss_svc_integrity
;
111 else if (strcasecmp(svc
, SVC_PRIVACY
) == 0)
112 *num
= rpc_gss_svc_privacy
;
113 else if (strcasecmp(svc
, SVC_NONE
) == 0)
114 *num
= rpc_gss_svc_none
;
115 else if (strcasecmp(svc
, SVC_DEFAULT
) == 0)
116 *num
= rpc_gss_svc_default
;
123 __rpc_gss_num_to_svc(rpc_gss_service_t num
)
126 case rpc_gss_svc_integrity
:
127 return (strdup(SVC_INTEGRITY
));
128 case rpc_gss_svc_privacy
:
129 return (strdup(SVC_PRIVACY
));
130 case rpc_gss_svc_none
:
131 return (strdup(SVC_NONE
));
132 case rpc_gss_svc_default
:
133 return (strdup(SVC_DEFAULT
));
140 * Given the user name, node, and security domain, get the mechanism
141 * specific principal name (for the user name) in exported form.
144 __rpc_gss_get_principal_name(rpc_gss_principal_t
*principal
, char *mech
,
145 char *user
, char *node
, char *secdomain
)
147 gss_name_t gss_name
, gss_canon_name
;
148 gss_buffer_desc name_buf
= GSS_C_EMPTY_BUFFER
;
149 char user_name
[256], *s
;
151 int nlen
= 0, slen
= 0, plen
;
152 OM_uint32 major
, minor
;
155 if (user
== NULL
|| strlen(user
) == 0)
158 if (!__rpc_gss_mech_to_oid(mech
, (rpc_gss_OID
*) &mech_oid
)) {
159 syslog(LOG_ERR
, "rpc_gss_get_principal_name: can't get"
164 if (secdomain
!= NULL
)
165 slen
= strlen(secdomain
);
170 strcpy(user_name
, user
);
172 strcat(user_name
, "/");
173 strcat(user_name
, node
);
177 strcat(user_name
, "@");
178 strcat(user_name
, secdomain
);
181 name_buf
.value
= user_name
;
182 name_buf
.length
= strlen(user_name
);
185 * Convert a text string to a GSSAPI Internal name.
187 if ((major
= gss_import_name(&minor
, &name_buf
,
188 (gss_OID
) GSS_C_NT_USER_NAME
, &gss_name
)) != GSS_S_COMPLETE
) {
189 syslog(LOG_ERR
, "rpc_gss_get_principal_name: import name"
190 "failed 0x%x", major
);
195 * Convert the GSSAPI Internal name to a MN - Mechanism Name
197 if ((major
= gss_canonicalize_name(&minor
, gss_name
, mech_oid
,
198 &gss_canon_name
)) != GSS_S_COMPLETE
) {
199 syslog(LOG_ERR
, "rpc_gss_get_principal_name: canonicalize name"
200 "failed 0x%x", major
);
201 gss_release_name(&minor
, &gss_name
);
204 gss_release_name(&minor
, &gss_name
);
207 * Convert the MN Internal name to an exported flat name, so
208 * it is suitable for binary comparison.
210 if ((major
= gss_export_name(&minor
, gss_canon_name
, &name_buf
)) !=
212 syslog(LOG_ERR
, "rpc_gss_get_principal_name: export name"
214 gss_release_name(&minor
, &gss_canon_name
);
217 gss_release_name(&minor
, &gss_canon_name
);
220 * Put the exported name into rpc_gss_principal_t structure.
222 plen
= RNDUP(name_buf
.length
) + sizeof (int);
223 (*principal
) = malloc(plen
);
224 if ((*principal
) == NULL
) {
225 gss_release_buffer(&minor
, &name_buf
);
228 bzero((caddr_t
)(*principal
), plen
);
229 (*principal
)->len
= RNDUP(name_buf
.length
);
230 s
= (*principal
)->name
;
231 memcpy(s
, name_buf
.value
, name_buf
.length
);
232 gss_release_buffer(&minor
, &name_buf
);
238 * Return supported mechanisms.
241 __rpc_gss_get_mechanisms(void)
243 static char *mech_list
[MAX_MECH_OID_PAIRS
+1];
246 __gss_get_mechanisms(mech_list
, MAX_MECH_OID_PAIRS
+1);
251 * For a given mechanism, return information about it.
254 * static char *krb5_qop_list[] = {Q_DEFAULT, NULL};
257 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
258 /* Don't know how to get the service type for a given mech. */
259 /* "service" should NOT be there! */
260 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*!!!!!!!!!!! */
263 __rpc_gss_get_mech_info(char *mech
, rpc_gss_service_t
*service
)
267 l
= calloc(MAX_QOPS_PER_MECH
+ 1, sizeof (char *));
271 if (__gss_get_mech_info(mech
, l
) != GSS_S_COMPLETE
) {
275 /* !!!!!!!!!!!!!!!! */
276 *service
= rpc_gss_svc_privacy
; /* What service type? */
277 /* !!!!!!!!!!!!!!!! */
282 * Returns highest and lowest versions of RPCSEC_GSS flavor supported.
285 __rpc_gss_get_versions(uint_t
*vers_hi
, uint_t
*vers_lo
)
287 *vers_hi
= RPCSEC_GSS_VERSION
;
288 *vers_lo
= RPCSEC_GSS_VERSION
;
293 * Check if a mechanism is installed.
296 __rpc_gss_is_installed(char *mech
)
303 if ((l
= __rpc_gss_get_mechanisms()) == NULL
)
307 if (strcmp(*l
, mech
) == 0)