1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1986-1995,1997, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <strings.h> 33 #include <errno.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <syslog.h> 37 #include <gssapi/gssapi.h> 38 #include <gssapi/gssapi_ext.h> 39 #include <rpc/rpc.h> 40 #include <rpc/rpcsec_defs.h> 41 #include <rpc/trace.h> 42 43 #define SVC_INTEGRITY "integrity" 44 #define SVC_PRIVACY "privacy" 45 #define SVC_NONE "none" 46 #define SVC_DEFAULT "default" 47 48 #define MCALL_MSG_SIZE 24 49 /* 50 * Private data kept per client handle 51 */ 52 struct cu_data { 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; 60 XDR cu_outxdrs; 61 char *cu_outbuf_start; 62 char cu_outbuf[MCALL_MSG_SIZE]; 63 u_int cu_xdrpos; 64 u_int cu_sendsz; /* send size */ 65 u_int cu_recvsz; /* recv size */ 66 struct pollfd pfdp; 67 char cu_inbuf[1]; 68 }; 69 70 /* 71 * Internal utility routines. 72 */ 73 bool_t 74 __rpc_gss_mech_to_oid(mech, oid) 75 char *mech; 76 rpc_gss_OID *oid; 77 { 78 79 if (__gss_mech_to_oid(mech, (gss_OID*)oid) != GSS_S_COMPLETE) 80 return (FALSE); 81 82 return (TRUE); 83 } 84 85 char * 86 __rpc_gss_oid_to_mech(oid) 87 rpc_gss_OID oid; 88 { 89 90 return ((char *)__gss_oid_to_mech((const gss_OID)oid)); 91 } 92 93 94 bool_t 95 __rpc_gss_qop_to_num(qop, mech, num) 96 char *qop; 97 char *mech; 98 OM_uint32 *num; 99 { 100 101 if (__gss_qop_to_num(qop, mech, num) != GSS_S_COMPLETE) 102 return (FALSE); 103 return (TRUE); 104 } 105 106 char * 107 __rpc_gss_num_to_qop(mech, num) 108 char *mech; 109 OM_uint32 num; 110 { 111 char *qop; 112 113 if (__gss_num_to_qop(mech, num, &qop) != GSS_S_COMPLETE) 114 return (NULL); 115 return (qop); 116 } 117 118 bool_t 119 __rpc_gss_svc_to_num(svc, num) 120 char *svc; 121 rpc_gss_service_t *num; 122 { 123 if (strcasecmp(svc, SVC_INTEGRITY) == 0) 124 *num = rpc_gss_svc_integrity; 125 else if (strcasecmp(svc, SVC_PRIVACY) == 0) 126 *num = rpc_gss_svc_privacy; 127 else if (strcasecmp(svc, SVC_NONE) == 0) 128 *num = rpc_gss_svc_none; 129 else if (strcasecmp(svc, SVC_DEFAULT) == 0) 130 *num = rpc_gss_svc_default; 131 else 132 return (FALSE); 133 return (TRUE); 134 } 135 136 char * 137 __rpc_gss_num_to_svc(num) 138 rpc_gss_service_t num; 139 { 140 switch (num) { 141 case rpc_gss_svc_integrity: 142 return (strdup(SVC_INTEGRITY)); 143 case rpc_gss_svc_privacy: 144 return (strdup(SVC_PRIVACY)); 145 case rpc_gss_svc_none: 146 return (strdup(SVC_NONE)); 147 case rpc_gss_svc_default: 148 return (strdup(SVC_DEFAULT)); 149 default: 150 return (NULL); 151 } 152 } 153 154 /* 155 * Given the user name, node, and security domain, get the mechanism 156 * specific principal name (for the user name) in exported form. 157 */ 158 bool_t 159 __rpc_gss_get_principal_name(principal, mech, user, node, secdomain) 160 rpc_gss_principal_t *principal; 161 char *mech; 162 char *user; 163 char *node; 164 char *secdomain; 165 { 166 gss_name_t gss_name, gss_canon_name; 167 gss_buffer_desc name_buf = GSS_C_EMPTY_BUFFER; 168 char user_name[256], *s; 169 gss_OID mech_oid; 170 int nlen = 0, slen = 0, plen; 171 OM_uint32 major, minor; 172 173 *principal = NULL; 174 if (user == NULL || strlen(user) == 0) 175 return (FALSE); 176 177 if (!__rpc_gss_mech_to_oid(mech, (rpc_gss_OID *) &mech_oid)) { 178 syslog(LOG_ERR, "rpc_gss_get_principal_name: can't get" 179 "mech oid"); 180 return (FALSE); 181 } 182 183 if (secdomain != NULL) 184 slen = strlen(secdomain); 185 186 if (node != NULL) 187 nlen = strlen(node); 188 189 strcpy(user_name, user); 190 if (nlen > 0) { 191 strcat(user_name, "/"); 192 strcat(user_name, node); 193 } 194 195 if (slen > 0) { 196 strcat(user_name, "@"); 197 strcat(user_name, secdomain); 198 } 199 200 name_buf.value = user_name; 201 name_buf.length = strlen(user_name); 202 203 /* 204 * Convert a text string to a GSSAPI Internal name. 205 */ 206 if ((major = gss_import_name(&minor, &name_buf, 207 (gss_OID) GSS_C_NT_USER_NAME, &gss_name)) != GSS_S_COMPLETE) { 208 syslog(LOG_ERR, "rpc_gss_get_principal_name: import name" 209 "failed 0x%x", major); 210 return (FALSE); 211 } 212 213 /* 214 * Convert the GSSAPI Internal name to a MN - Mechanism Name 215 */ 216 if ((major = gss_canonicalize_name(&minor, gss_name, mech_oid, 217 &gss_canon_name)) != GSS_S_COMPLETE) { 218 syslog(LOG_ERR, "rpc_gss_get_principal_name: canonicalize name" 219 "failed 0x%x", major); 220 gss_release_name(&minor, &gss_name); 221 return (FALSE); 222 } 223 gss_release_name(&minor, &gss_name); 224 225 /* 226 * Convert the MN Internal name to an exported flat name, so 227 * it is suitable for binary comparison. 228 */ 229 if ((major = gss_export_name(&minor, gss_canon_name, &name_buf)) != 230 GSS_S_COMPLETE) { 231 syslog(LOG_ERR, "rpc_gss_get_principal_name: export name" 232 "failed %x", major); 233 gss_release_name(&minor, &gss_canon_name); 234 return (FALSE); 235 } 236 gss_release_name(&minor, &gss_canon_name); 237 238 /* 239 * Put the exported name into rpc_gss_principal_t structure. 240 */ 241 plen = RNDUP(name_buf.length) + sizeof (int); 242 (*principal) = (rpc_gss_principal_t)malloc(plen); 243 if ((*principal) == NULL) { 244 gss_release_buffer(&minor, &name_buf); 245 return (FALSE); 246 } 247 bzero((caddr_t)(*principal), plen); 248 (*principal)->len = RNDUP(name_buf.length); 249 s = (*principal)->name; 250 memcpy(s, name_buf.value, name_buf.length); 251 gss_release_buffer(&minor, &name_buf); 252 253 return (TRUE); 254 } 255 256 /* 257 * Return supported mechanisms. 258 */ 259 char ** 260 __rpc_gss_get_mechanisms() 261 { 262 static char *mech_list[MAX_MECH_OID_PAIRS+1]; 263 264 *mech_list = NULL; 265 __gss_get_mechanisms(mech_list, MAX_MECH_OID_PAIRS+1); 266 return (mech_list); 267 } 268 269 /* 270 * For a given mechanism, return information about it. 271 */ 272 /* 273 * static char *krb5_qop_list[] = {Q_DEFAULT, NULL}; 274 */ 275 276 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 277 /* Don't know how to get the service type for a given mech. */ 278 /* "service" should NOT be there! */ 279 /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*!!!!!!!!!!! */ 280 281 char ** 282 __rpc_gss_get_mech_info(mech, service) 283 char *mech; 284 rpc_gss_service_t *service; 285 { 286 char **l; 287 288 l = calloc(MAX_QOPS_PER_MECH + 1, sizeof (char *)); 289 if (l == NULL) 290 return (NULL); 291 292 if (__gss_get_mech_info(mech, l) != GSS_S_COMPLETE) { 293 free(l); 294 return (NULL); 295 } 296 /* !!!!!!!!!!!!!!!! */ 297 *service = rpc_gss_svc_privacy; /* What service type? */ 298 /* !!!!!!!!!!!!!!!! */ 299 return (l); 300 } 301 302 /* 303 * Returns highest and lowest versions of RPCSEC_GSS flavor supported. 304 */ 305 bool_t 306 __rpc_gss_get_versions(vers_hi, vers_lo) 307 u_int *vers_hi; 308 u_int *vers_lo; 309 { 310 *vers_hi = RPCSEC_GSS_VERSION; 311 *vers_lo = RPCSEC_GSS_VERSION; 312 return (TRUE); 313 } 314 315 /* 316 * Check if a mechanism is installed. 317 */ 318 bool_t 319 __rpc_gss_is_installed(mech) 320 char *mech; 321 { 322 char **l; 323 324 if (mech == NULL) 325 return (FALSE); 326 327 if ((l = __rpc_gss_get_mechanisms()) == NULL) 328 return (FALSE); 329 330 while (*l != NULL) { 331 if (strcmp(*l, mech) == 0) 332 return (TRUE); 333 l++; 334 } 335 return (FALSE); 336 } 337