18f55a568SDoug Rabson /*- 2*5e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*5e53a4f9SPedro F. Giffuni * 48f55a568SDoug Rabson * Copyright (c) 2008 Doug Rabson 58f55a568SDoug Rabson * All rights reserved. 68f55a568SDoug Rabson * 78f55a568SDoug Rabson * Redistribution and use in source and binary forms, with or without 88f55a568SDoug Rabson * modification, are permitted provided that the following conditions 98f55a568SDoug Rabson * are met: 108f55a568SDoug Rabson * 1. Redistributions of source code must retain the above copyright 118f55a568SDoug Rabson * notice, this list of conditions and the following disclaimer. 128f55a568SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 138f55a568SDoug Rabson * notice, this list of conditions and the following disclaimer in the 148f55a568SDoug Rabson * documentation and/or other materials provided with the distribution. 158f55a568SDoug Rabson * 168f55a568SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 178f55a568SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 188f55a568SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198f55a568SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 208f55a568SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 218f55a568SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 228f55a568SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 238f55a568SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 248f55a568SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 258f55a568SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 268f55a568SDoug Rabson * SUCH DAMAGE. 278f55a568SDoug Rabson * 288f55a568SDoug Rabson * $FreeBSD$ 298f55a568SDoug Rabson */ 308f55a568SDoug Rabson 318f55a568SDoug Rabson #include <ctype.h> 328f55a568SDoug Rabson #include <stdio.h> 338f55a568SDoug Rabson #include <string.h> 348f55a568SDoug Rabson #include <stdlib.h> 358f55a568SDoug Rabson #include <errno.h> 368f55a568SDoug Rabson #include <sys/queue.h> 378f55a568SDoug Rabson #include <rpc/rpc.h> 388f55a568SDoug Rabson #include <rpc/rpcsec_gss.h> 398f55a568SDoug Rabson 408f55a568SDoug Rabson #include "rpcsec_gss_int.h" 418f55a568SDoug Rabson 428f55a568SDoug Rabson #ifndef _PATH_GSS_MECH 438f55a568SDoug Rabson #define _PATH_GSS_MECH "/etc/gss/mech" 448f55a568SDoug Rabson #endif 458f55a568SDoug Rabson 468f55a568SDoug Rabson #ifndef _PATH_GSS_QOP 478f55a568SDoug Rabson #define _PATH_GSS_QOP "/etc/gss/qop" 488f55a568SDoug Rabson #endif 498f55a568SDoug Rabson 508f55a568SDoug Rabson struct mech_info { 518f55a568SDoug Rabson SLIST_ENTRY(mech_info) link; 528f55a568SDoug Rabson char *name; 538f55a568SDoug Rabson gss_OID_desc oid; 548f55a568SDoug Rabson const char **qops; 558f55a568SDoug Rabson char *lib; 568f55a568SDoug Rabson char *kobj; 578f55a568SDoug Rabson }; 588f55a568SDoug Rabson SLIST_HEAD(mech_info_list, mech_info); 598f55a568SDoug Rabson 6013e403fdSAntoine Brodin static struct mech_info_list mechs = SLIST_HEAD_INITIALIZER(mechs); 618f55a568SDoug Rabson static const char **mech_names; 628f55a568SDoug Rabson 638f55a568SDoug Rabson struct qop_info { 648f55a568SDoug Rabson SLIST_ENTRY(qop_info) link; 658f55a568SDoug Rabson char *name; 668f55a568SDoug Rabson char* mech; 678f55a568SDoug Rabson u_int qop; 688f55a568SDoug Rabson }; 698f55a568SDoug Rabson SLIST_HEAD(qop_info_list, qop_info); 708f55a568SDoug Rabson 7113e403fdSAntoine Brodin static struct qop_info_list qops = SLIST_HEAD_INITIALIZER(qops); 728f55a568SDoug Rabson 738f55a568SDoug Rabson static int 748f55a568SDoug Rabson _rpc_gss_string_to_oid(const char* s, gss_OID oid) 758f55a568SDoug Rabson { 768f55a568SDoug Rabson int number_count, i, j; 778f55a568SDoug Rabson int byte_count; 788f55a568SDoug Rabson const char *p, *q; 798f55a568SDoug Rabson char *res; 808f55a568SDoug Rabson 818f55a568SDoug Rabson /* 828f55a568SDoug Rabson * First figure out how many numbers in the oid, then 838f55a568SDoug Rabson * calculate the compiled oid size. 848f55a568SDoug Rabson */ 858f55a568SDoug Rabson number_count = 0; 868f55a568SDoug Rabson for (p = s; p; p = q) { 878f55a568SDoug Rabson q = strchr(p, '.'); 888f55a568SDoug Rabson if (q) q = q + 1; 898f55a568SDoug Rabson number_count++; 908f55a568SDoug Rabson } 918f55a568SDoug Rabson 928f55a568SDoug Rabson /* 938f55a568SDoug Rabson * The first two numbers are in the first byte and each 948f55a568SDoug Rabson * subsequent number is encoded in a variable byte sequence. 958f55a568SDoug Rabson */ 968f55a568SDoug Rabson if (number_count < 2) 978f55a568SDoug Rabson return (EINVAL); 988f55a568SDoug Rabson 998f55a568SDoug Rabson /* 1008f55a568SDoug Rabson * We do this in two passes. The first pass, we just figure 1018f55a568SDoug Rabson * out the size. Second time around, we actually encode the 1028f55a568SDoug Rabson * number. 1038f55a568SDoug Rabson */ 1048f55a568SDoug Rabson res = 0; 1058f55a568SDoug Rabson for (i = 0; i < 2; i++) { 1068f55a568SDoug Rabson byte_count = 0; 1078f55a568SDoug Rabson for (p = s, j = 0; p; p = q, j++) { 1088f55a568SDoug Rabson u_int number = 0; 1098f55a568SDoug Rabson 1108f55a568SDoug Rabson /* 1118f55a568SDoug Rabson * Find the end of this number. 1128f55a568SDoug Rabson */ 1138f55a568SDoug Rabson q = strchr(p, '.'); 1148f55a568SDoug Rabson if (q) q = q + 1; 1158f55a568SDoug Rabson 1168f55a568SDoug Rabson /* 1178f55a568SDoug Rabson * Read the number of of the string. Don't 1188f55a568SDoug Rabson * bother with anything except base ten. 1198f55a568SDoug Rabson */ 1208f55a568SDoug Rabson while (*p && *p != '.') { 1218f55a568SDoug Rabson number = 10 * number + (*p - '0'); 1228f55a568SDoug Rabson p++; 1238f55a568SDoug Rabson } 1248f55a568SDoug Rabson 1258f55a568SDoug Rabson /* 1268f55a568SDoug Rabson * Encode the number. The first two numbers 1278f55a568SDoug Rabson * are packed into the first byte. Subsequent 1288f55a568SDoug Rabson * numbers are encoded in bytes seven bits at 1298f55a568SDoug Rabson * a time with the last byte having the high 1308f55a568SDoug Rabson * bit set. 1318f55a568SDoug Rabson */ 1328f55a568SDoug Rabson if (j == 0) { 1338f55a568SDoug Rabson if (res) 1348f55a568SDoug Rabson *res = number * 40; 1358f55a568SDoug Rabson } else if (j == 1) { 1368f55a568SDoug Rabson if (res) { 1378f55a568SDoug Rabson *res += number; 1388f55a568SDoug Rabson res++; 1398f55a568SDoug Rabson } 1408f55a568SDoug Rabson byte_count++; 1418f55a568SDoug Rabson } else if (j >= 2) { 1428f55a568SDoug Rabson /* 1438f55a568SDoug Rabson * The number is encoded in seven bit chunks. 1448f55a568SDoug Rabson */ 1458f55a568SDoug Rabson u_int t; 1468f55a568SDoug Rabson int bytes; 1478f55a568SDoug Rabson 1488f55a568SDoug Rabson bytes = 0; 1498f55a568SDoug Rabson for (t = number; t; t >>= 7) 1508f55a568SDoug Rabson bytes++; 1518f55a568SDoug Rabson if (bytes == 0) bytes = 1; 1528f55a568SDoug Rabson while (bytes) { 1538f55a568SDoug Rabson if (res) { 1548f55a568SDoug Rabson int bit = 7*(bytes-1); 1558f55a568SDoug Rabson 1568f55a568SDoug Rabson *res = (number >> bit) & 0x7f; 1578f55a568SDoug Rabson if (bytes != 1) 1588f55a568SDoug Rabson *res |= 0x80; 1598f55a568SDoug Rabson res++; 1608f55a568SDoug Rabson } 1618f55a568SDoug Rabson byte_count++; 1628f55a568SDoug Rabson bytes--; 1638f55a568SDoug Rabson } 1648f55a568SDoug Rabson } 1658f55a568SDoug Rabson } 1668f55a568SDoug Rabson if (!res) { 1678f55a568SDoug Rabson res = malloc(byte_count); 1688f55a568SDoug Rabson if (!res) 1698f55a568SDoug Rabson return (ENOMEM); 1708f55a568SDoug Rabson oid->length = byte_count; 1718f55a568SDoug Rabson oid->elements = res; 1728f55a568SDoug Rabson } 1738f55a568SDoug Rabson } 1748f55a568SDoug Rabson 1758f55a568SDoug Rabson return (0); 1768f55a568SDoug Rabson } 1778f55a568SDoug Rabson 1788f55a568SDoug Rabson static void 1798f55a568SDoug Rabson _rpc_gss_load_mech(void) 1808f55a568SDoug Rabson { 1818f55a568SDoug Rabson FILE *fp; 1828f55a568SDoug Rabson char buf[256]; 1838f55a568SDoug Rabson char *p; 1848f55a568SDoug Rabson char *name, *oid, *lib, *kobj; 1858f55a568SDoug Rabson struct mech_info *info; 1868f55a568SDoug Rabson int count; 1878f55a568SDoug Rabson const char **pp; 1888f55a568SDoug Rabson 1898f55a568SDoug Rabson if (SLIST_FIRST(&mechs)) 1908f55a568SDoug Rabson return; 1918f55a568SDoug Rabson 1928f55a568SDoug Rabson fp = fopen(_PATH_GSS_MECH, "r"); 1938f55a568SDoug Rabson if (!fp) 1948f55a568SDoug Rabson return; 1958f55a568SDoug Rabson 1968f55a568SDoug Rabson count = 0; 1978f55a568SDoug Rabson while (fgets(buf, sizeof(buf), fp)) { 1988f55a568SDoug Rabson if (*buf == '#') 1998f55a568SDoug Rabson continue; 2008f55a568SDoug Rabson p = buf; 2018f55a568SDoug Rabson name = strsep(&p, "\t\n "); 2028f55a568SDoug Rabson if (p) while (isspace(*p)) p++; 2038f55a568SDoug Rabson oid = strsep(&p, "\t\n "); 2048f55a568SDoug Rabson if (p) while (isspace(*p)) p++; 2058f55a568SDoug Rabson lib = strsep(&p, "\t\n "); 2068f55a568SDoug Rabson if (p) while (isspace(*p)) p++; 2078f55a568SDoug Rabson kobj = strsep(&p, "\t\n "); 2088f55a568SDoug Rabson if (!name || !oid || !lib || !kobj) 2098f55a568SDoug Rabson continue; 2108f55a568SDoug Rabson 2118f55a568SDoug Rabson info = malloc(sizeof(struct mech_info)); 2128f55a568SDoug Rabson if (!info) 2138f55a568SDoug Rabson break; 2148f55a568SDoug Rabson if (_rpc_gss_string_to_oid(oid, &info->oid)) { 2158f55a568SDoug Rabson free(info); 2168f55a568SDoug Rabson continue; 2178f55a568SDoug Rabson } 2188f55a568SDoug Rabson info->name = strdup(name); 2198f55a568SDoug Rabson info->qops = NULL; 2208f55a568SDoug Rabson info->lib = strdup(lib); 2218f55a568SDoug Rabson info->kobj = strdup(kobj); 2228f55a568SDoug Rabson SLIST_INSERT_HEAD(&mechs, info, link); 2238f55a568SDoug Rabson count++; 2248f55a568SDoug Rabson } 2258f55a568SDoug Rabson fclose(fp); 2268f55a568SDoug Rabson 2278f55a568SDoug Rabson mech_names = malloc((count + 1) * sizeof(char*)); 2288f55a568SDoug Rabson pp = mech_names; 2298f55a568SDoug Rabson SLIST_FOREACH(info, &mechs, link) { 2308f55a568SDoug Rabson *pp++ = info->name; 2318f55a568SDoug Rabson } 2328f55a568SDoug Rabson *pp = NULL; 2338f55a568SDoug Rabson } 2348f55a568SDoug Rabson 2358f55a568SDoug Rabson static void 2368f55a568SDoug Rabson _rpc_gss_load_qop(void) 2378f55a568SDoug Rabson { 2388f55a568SDoug Rabson FILE *fp; 2398f55a568SDoug Rabson char buf[256]; 2408f55a568SDoug Rabson char *p; 2418f55a568SDoug Rabson char *name, *num, *mech; 2428f55a568SDoug Rabson struct mech_info *minfo; 2438f55a568SDoug Rabson struct qop_info *info; 2448f55a568SDoug Rabson int count; 2458f55a568SDoug Rabson const char **mech_qops; 2468f55a568SDoug Rabson const char **pp; 2478f55a568SDoug Rabson 2488f55a568SDoug Rabson if (SLIST_FIRST(&qops)) 2498f55a568SDoug Rabson return; 2508f55a568SDoug Rabson 2518f55a568SDoug Rabson fp = fopen(_PATH_GSS_QOP, "r"); 2528f55a568SDoug Rabson if (!fp) 2538f55a568SDoug Rabson return; 2548f55a568SDoug Rabson 2558f55a568SDoug Rabson while (fgets(buf, sizeof(buf), fp)) { 2568f55a568SDoug Rabson if (*buf == '#') 2578f55a568SDoug Rabson continue; 2588f55a568SDoug Rabson p = buf; 2598f55a568SDoug Rabson name = strsep(&p, "\t\n "); 2608f55a568SDoug Rabson if (p) while (isspace(*p)) p++; 2618f55a568SDoug Rabson num = strsep(&p, "\t\n "); 2628f55a568SDoug Rabson if (p) while (isspace(*p)) p++; 2638f55a568SDoug Rabson mech = strsep(&p, "\t\n "); 2648f55a568SDoug Rabson if (!name || !num || !mech) 2658f55a568SDoug Rabson continue; 2668f55a568SDoug Rabson 2678f55a568SDoug Rabson info = malloc(sizeof(struct qop_info)); 2688f55a568SDoug Rabson if (!info) 2698f55a568SDoug Rabson break; 2708f55a568SDoug Rabson info->name = strdup(name); 2718f55a568SDoug Rabson info->qop = strtoul(name, 0, 0); 2728f55a568SDoug Rabson info->mech = strdup(mech); 2738f55a568SDoug Rabson SLIST_INSERT_HEAD(&qops, info, link); 2748f55a568SDoug Rabson } 2758f55a568SDoug Rabson fclose(fp); 2768f55a568SDoug Rabson 2778f55a568SDoug Rabson /* 2788f55a568SDoug Rabson * Compile lists of qops for each mechanism. 2798f55a568SDoug Rabson */ 2808f55a568SDoug Rabson SLIST_FOREACH(minfo, &mechs, link) { 2818f55a568SDoug Rabson count = 0; 2828f55a568SDoug Rabson SLIST_FOREACH(info, &qops, link) { 2838f55a568SDoug Rabson if (strcmp(info->mech, minfo->name) == 0) 2848f55a568SDoug Rabson count++; 2858f55a568SDoug Rabson } 2868f55a568SDoug Rabson mech_qops = malloc((count + 1) * sizeof(char*)); 2878f55a568SDoug Rabson pp = mech_qops; 2888f55a568SDoug Rabson SLIST_FOREACH(info, &qops, link) { 2898f55a568SDoug Rabson if (strcmp(info->mech, minfo->name) == 0) 2908f55a568SDoug Rabson *pp++ = info->name; 2918f55a568SDoug Rabson } 2928f55a568SDoug Rabson *pp = NULL; 2938f55a568SDoug Rabson minfo->qops = mech_qops; 2948f55a568SDoug Rabson } 2958f55a568SDoug Rabson } 2968f55a568SDoug Rabson 2978f55a568SDoug Rabson bool_t 2988f55a568SDoug Rabson rpc_gss_mech_to_oid(const char *mech, gss_OID *oid_ret) 2998f55a568SDoug Rabson { 3008f55a568SDoug Rabson struct mech_info *info; 3018f55a568SDoug Rabson 3028f55a568SDoug Rabson _rpc_gss_load_mech(); 3038f55a568SDoug Rabson SLIST_FOREACH(info, &mechs, link) { 3048f55a568SDoug Rabson if (!strcmp(info->name, mech)) { 3058f55a568SDoug Rabson *oid_ret = &info->oid; 3068f55a568SDoug Rabson return (TRUE); 3078f55a568SDoug Rabson } 3088f55a568SDoug Rabson } 3098f55a568SDoug Rabson _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOENT); 3108f55a568SDoug Rabson return (FALSE); 3118f55a568SDoug Rabson } 3128f55a568SDoug Rabson 3138f55a568SDoug Rabson bool_t 3148f55a568SDoug Rabson rpc_gss_oid_to_mech(gss_OID oid, const char **mech_ret) 3158f55a568SDoug Rabson { 3168f55a568SDoug Rabson struct mech_info *info; 3178f55a568SDoug Rabson 3188f55a568SDoug Rabson _rpc_gss_load_mech(); 3198f55a568SDoug Rabson SLIST_FOREACH(info, &mechs, link) { 3208f55a568SDoug Rabson if (oid->length == info->oid.length 3218f55a568SDoug Rabson && !memcmp(oid->elements, info->oid.elements, 3228f55a568SDoug Rabson oid->length)) { 3238f55a568SDoug Rabson *mech_ret = info->name; 3248f55a568SDoug Rabson return (TRUE); 3258f55a568SDoug Rabson } 3268f55a568SDoug Rabson } 3278f55a568SDoug Rabson _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOENT); 3288f55a568SDoug Rabson return (FALSE); 3298f55a568SDoug Rabson } 3308f55a568SDoug Rabson 3318f55a568SDoug Rabson bool_t 3328f55a568SDoug Rabson rpc_gss_qop_to_num(const char *qop, const char *mech, u_int *num_ret) 3338f55a568SDoug Rabson { 3348f55a568SDoug Rabson struct qop_info *info; 3358f55a568SDoug Rabson 3368f55a568SDoug Rabson _rpc_gss_load_qop(); 3378f55a568SDoug Rabson SLIST_FOREACH(info, &qops, link) { 3388f55a568SDoug Rabson if (strcmp(info->name, qop) == 0 3398f55a568SDoug Rabson && strcmp(info->mech, mech) == 0) { 3408f55a568SDoug Rabson *num_ret = info->qop; 3418f55a568SDoug Rabson return (TRUE); 3428f55a568SDoug Rabson } 3438f55a568SDoug Rabson } 3448f55a568SDoug Rabson _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOENT); 3458f55a568SDoug Rabson return (FALSE); 3468f55a568SDoug Rabson } 3478f55a568SDoug Rabson 3488f55a568SDoug Rabson const char * 3498f55a568SDoug Rabson _rpc_gss_num_to_qop(const char *mech, u_int num) 3508f55a568SDoug Rabson { 3518f55a568SDoug Rabson struct qop_info *info; 3528f55a568SDoug Rabson 3538f55a568SDoug Rabson if (num == GSS_C_QOP_DEFAULT) 3548f55a568SDoug Rabson return "default"; 3558f55a568SDoug Rabson 3568f55a568SDoug Rabson _rpc_gss_load_qop(); 3578f55a568SDoug Rabson SLIST_FOREACH(info, &qops, link) { 3588f55a568SDoug Rabson if (info->qop == num && strcmp(info->mech, mech) == 0) { 3598f55a568SDoug Rabson return (info->name); 3608f55a568SDoug Rabson } 3618f55a568SDoug Rabson } 3628f55a568SDoug Rabson return (NULL); 3638f55a568SDoug Rabson } 3648f55a568SDoug Rabson 3658f55a568SDoug Rabson const char ** 3668f55a568SDoug Rabson rpc_gss_get_mechanisms(void) 3678f55a568SDoug Rabson { 3688f55a568SDoug Rabson 3698f55a568SDoug Rabson _rpc_gss_load_mech(); 3708f55a568SDoug Rabson return (mech_names); 3718f55a568SDoug Rabson } 3728f55a568SDoug Rabson 3738f55a568SDoug Rabson const char ** 3748f55a568SDoug Rabson rpc_gss_get_mech_info(const char *mech, rpc_gss_service_t *service) 3758f55a568SDoug Rabson { 3768f55a568SDoug Rabson struct mech_info *info; 3778f55a568SDoug Rabson 3788f55a568SDoug Rabson _rpc_gss_load_mech(); 3798f55a568SDoug Rabson _rpc_gss_load_qop(); 3808f55a568SDoug Rabson SLIST_FOREACH(info, &mechs, link) { 3818f55a568SDoug Rabson if (!strcmp(mech, info->name)) { 3828f55a568SDoug Rabson /* 3838f55a568SDoug Rabson * I'm not sure what to do with service 3848f55a568SDoug Rabson * here. The Solaris manpages are not clear on 3858f55a568SDoug Rabson * the subject and the OpenSolaris code just 3868f55a568SDoug Rabson * sets it to rpc_gss_svc_privacy 3878f55a568SDoug Rabson * unconditionally with a comment noting that 3888f55a568SDoug Rabson * it is bogus. 3898f55a568SDoug Rabson */ 3908f55a568SDoug Rabson *service = rpc_gss_svc_privacy; 3918f55a568SDoug Rabson return info->qops; 3928f55a568SDoug Rabson } 3938f55a568SDoug Rabson } 3948f55a568SDoug Rabson 3958f55a568SDoug Rabson _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOENT); 3968f55a568SDoug Rabson return (NULL); 3978f55a568SDoug Rabson } 3988f55a568SDoug Rabson 3998f55a568SDoug Rabson bool_t 4008f55a568SDoug Rabson rpc_gss_get_versions(u_int *vers_hi, u_int *vers_lo) 4018f55a568SDoug Rabson { 4028f55a568SDoug Rabson 4038f55a568SDoug Rabson *vers_hi = 1; 4048f55a568SDoug Rabson *vers_lo = 1; 4058f55a568SDoug Rabson return (TRUE); 4068f55a568SDoug Rabson } 4078f55a568SDoug Rabson 4088f55a568SDoug Rabson bool_t 4098f55a568SDoug Rabson rpc_gss_is_installed(const char *mech) 4108f55a568SDoug Rabson { 4118f55a568SDoug Rabson struct mech_info *info; 4128f55a568SDoug Rabson 4138f55a568SDoug Rabson _rpc_gss_load_mech(); 4148f55a568SDoug Rabson SLIST_FOREACH(info, &mechs, link) 4158f55a568SDoug Rabson if (!strcmp(mech, info->name)) 4168f55a568SDoug Rabson return (TRUE); 4178f55a568SDoug Rabson return (FALSE); 4188f55a568SDoug Rabson } 4198f55a568SDoug Rabson 420