gss_impl.c revision 224084
1139804Simp/*- 246197Sphk * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 346197Sphk * Authors: Doug Rabson <dfr@rabson.org> 446197Sphk * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 546197Sphk * 646197Sphk * Redistribution and use in source and binary forms, with or without 746197Sphk * modification, are permitted provided that the following conditions 846197Sphk * are met: 946155Sphk * 1. Redistributions of source code must retain the above copyright 10116182Sobrien * notice, this list of conditions and the following disclaimer. 11116182Sobrien * 2. Redistributions in binary form must reproduce the above copyright 12116182Sobrien * notice, this list of conditions and the following disclaimer in the 13131177Spjd * documentation and/or other materials provided with the distribution. 14131177Spjd * 1546155Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1646155Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1746155Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1846155Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1946155Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2046155Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2146155Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22164032Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2346155Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24124882Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2546155Sphk * SUCH DAMAGE. 2687275Srwatson */ 2787275Srwatson 28168401Spjd#include <sys/cdefs.h> 29113275Smike__FBSDID("$FreeBSD: head/sys/kgssapi/gss_impl.c 224084 2011-07-16 08:05:49Z zack $"); 30147185Spjd 31113275Smike#include <sys/param.h> 3246155Sphk#include <sys/kernel.h> 33113275Smike#include <sys/kobj.h> 3457163Srwatson#include <sys/malloc.h> 35113275Smike#include <sys/module.h> 3646155Sphk#include <sys/priv.h> 3746155Sphk#include <sys/syscall.h> 3846155Sphk#include <sys/sysent.h> 39163606Srwatson#include <sys/sysproto.h> 40163606Srwatson 4146155Sphk#include <kgssapi/gssapi.h> 4246155Sphk#include <kgssapi/gssapi_impl.h> 4389414Sarr#include <rpc/rpc.h> 4457163Srwatson#include <rpc/rpc_com.h> 4557163Srwatson#include <rpc/rpcsec_gss.h> 4657163Srwatson 4789414Sarr#include "gssd.h" 4857163Srwatson#include "kgss_if.h" 4957163Srwatson 5057163SrwatsonMALLOC_DEFINE(M_GSSAPI, "GSS-API", "GSS-API"); 5161235Srwatson 5289414Sarr/* 5361235Srwatson * Syscall hooks 5461235Srwatson */ 5561235Srwatsonstatic int gssd_syscall_offset = SYS_gssd_syscall; 5668024Srwatsonstatic struct sysent gssd_syscall_prev_sysent; 5789414SarrMAKE_SYSENT(gssd_syscall); 5868024Srwatsonstatic bool_t gssd_syscall_registered = FALSE; 5968024Srwatson 6068024Srwatsonstruct kgss_mech_list kgss_mechs; 61147185SpjdCLIENT *kgss_gssd_handle; 62147185Spjd 63147185Spjdstatic void 64147185Spjdkgss_init(void *dummy) 65125804Srwatson{ 66128664Sbmilekic int error; 67128664Sbmilekic 68128664Sbmilekic LIST_INIT(&kgss_mechs); 69128664Sbmilekic error = syscall_register(&gssd_syscall_offset, &gssd_syscall_sysent, 70128664Sbmilekic &gssd_syscall_prev_sysent); 71141543Scperciva if (error) 72141543Scperciva printf("Can't register GSSD syscall\n"); 73141543Scperciva else 74141543Scperciva gssd_syscall_registered = TRUE; 75141543Scperciva} 76168396SpjdSYSINIT(kgss_init, SI_SUB_LOCK, SI_ORDER_FIRST, kgss_init, NULL); 77168396Spjd 78168396Spjdstatic void 79168396Spjdkgss_uninit(void *dummy) 80168396Spjd{ 81168401Spjd 82113275Smike if (gssd_syscall_registered) 83168401Spjd syscall_deregister(&gssd_syscall_offset, 84113275Smike &gssd_syscall_prev_sysent); 85113275Smike} 86113275SmikeSYSUNINIT(kgss_uninit, SI_SUB_LOCK, SI_ORDER_FIRST, kgss_uninit, NULL); 87168401Spjd 88168401Spjdint 89168401Spjdgssd_syscall(struct thread *td, struct gssd_syscall_args *uap) 90168401Spjd{ 91168401Spjd struct sockaddr_un sun; 92168401Spjd struct netconfig *nconf; 93168401Spjd char path[MAXPATHLEN]; 94168401Spjd int error; 95168401Spjd 96168401Spjd error = priv_check(td, PRIV_NFS_DAEMON); 97168401Spjd if (error) 98168401Spjd return (error); 99168401Spjd 100168401Spjd if (kgss_gssd_handle) 101168401Spjd CLNT_DESTROY(kgss_gssd_handle); 102168401Spjd 103113275Smike error = copyinstr(uap->path, path, sizeof(path), NULL); 104124882Srwatson if (error) 105113275Smike return (error); 106113275Smike 107113275Smike sun.sun_family = AF_LOCAL; 108113275Smike strcpy(sun.sun_path, path); 109113275Smike sun.sun_len = SUN_LEN(&sun); 110113275Smike 111168401Spjd nconf = getnetconfigent("local"); 112113275Smike kgss_gssd_handle = clnt_reconnect_create(nconf, 113113275Smike (struct sockaddr *) &sun, GSSD, GSSDVERS, 114113275Smike RPC_MAXDATASIZE, RPC_MAXDATASIZE); 115113275Smike 116113275Smike return (0); 11782710Sdillon} 118114168Smike 119114168Smikeint 120114168Smikekgss_oid_equal(const gss_OID oid1, const gss_OID oid2) 12182710Sdillon{ 12246155Sphk 123114168Smike if (oid1 == oid2) 12446155Sphk return (1); 125113275Smike if (!oid1 || !oid2) 126113275Smike return (0); 127168401Spjd if (oid1->length != oid2->length) 12846155Sphk return (0); 129113275Smike if (memcmp(oid1->elements, oid2->elements, oid1->length)) 130150652Scsjp return (0); 13146155Sphk return (1); 132114168Smike} 13346155Sphk 13484828Sjhbvoid 13584828Sjhbkgss_install_mech(gss_OID mech_type, const char *name, struct kobj_class *cls) 13684828Sjhb{ 13784828Sjhb struct kgss_mech *km; 138114168Smike 13993818Sjhb km = malloc(sizeof(struct kgss_mech), M_GSSAPI, M_WAITOK); 140113275Smike km->km_mech_type = mech_type; 141114168Smike km->km_mech_name = name; 142113275Smike km->km_class = cls; 143113275Smike LIST_INSERT_HEAD(&kgss_mechs, km, km_link); 144150652Scsjp} 145150652Scsjp 146113275Smikevoid 147150652Scsjpkgss_uninstall_mech(gss_OID mech_type) 148113275Smike{ 149150652Scsjp struct kgss_mech *km; 150113275Smike 151113275Smike LIST_FOREACH(km, &kgss_mechs, km_link) { 152113275Smike if (kgss_oid_equal(km->km_mech_type, mech_type)) { 153150652Scsjp LIST_REMOVE(km, km_link); 154114168Smike free(km, M_GSSAPI); 15584828Sjhb return; 156113275Smike } 157113275Smike } 158113275Smike} 159113275Smike 160168401Spjdgss_OID 161168401Spjdkgss_find_mech_by_name(const char *name) 162168401Spjd{ 163168401Spjd struct kgss_mech *km; 164168401Spjd 165168401Spjd LIST_FOREACH(km, &kgss_mechs, km_link) { 166113275Smike if (!strcmp(km->km_mech_name, name)) { 167113275Smike return (km->km_mech_type); 168168401Spjd } 169113275Smike } 170113275Smike return (GSS_C_NO_OID); 171113275Smike} 172113275Smike 173113275Smikeconst char * 174113275Smikekgss_find_mech_by_oid(const gss_OID oid) 175113275Smike{ 176113275Smike struct kgss_mech *km; 177168401Spjd 178113275Smike LIST_FOREACH(km, &kgss_mechs, km_link) { 179113275Smike if (kgss_oid_equal(km->km_mech_type, oid)) { 180113275Smike return (km->km_mech_name); 181113275Smike } 182113275Smike } 183113275Smike return (NULL); 184113275Smike} 185113275Smike 186113275Smikegss_ctx_id_t 187168401Spjdkgss_create_context(gss_OID mech_type) 188168401Spjd{ 189168401Spjd struct kgss_mech *km; 190168401Spjd gss_ctx_id_t ctx; 191168401Spjd 192113275Smike LIST_FOREACH(km, &kgss_mechs, km_link) { 193113275Smike if (kgss_oid_equal(km->km_mech_type, mech_type)) 194113275Smike break; 195113275Smike } 196113275Smike if (!km) 197113275Smike return (NULL); 198113275Smike 199113275Smike ctx = (gss_ctx_id_t) kobj_create(km->km_class, M_GSSAPI, M_WAITOK); 200113275Smike KGSS_INIT(ctx); 201113275Smike 202168401Spjd return (ctx); 203113275Smike} 204113275Smike 205168401Spjdvoid 206168401Spjdkgss_delete_context(gss_ctx_id_t ctx, gss_buffer_t output_token) 207168401Spjd{ 208168401Spjd 209168401Spjd KGSS_DELETE(ctx, output_token); 210113275Smike kobj_delete((kobj_t) ctx, M_GSSAPI); 211150652Scsjp} 212113275Smike 213150652ScsjpOM_uint32 214113275Smikekgss_transfer_context(gss_ctx_id_t ctx) 215113275Smike{ 216113275Smike struct export_sec_context_res res; 217113275Smike struct export_sec_context_args args; 218113275Smike enum clnt_stat stat; 219113275Smike OM_uint32 maj_stat; 220113275Smike 221114168Smike if (!kgss_gssd_handle) 222114168Smike return (GSS_S_FAILURE); 223114168Smike 224113275Smike args.ctx = ctx->handle; 225113275Smike bzero(&res, sizeof(res)); 226114168Smike stat = gssd_export_sec_context_1(&args, &res, kgss_gssd_handle); 227113275Smike if (stat != RPC_SUCCESS) { 228113275Smike return (GSS_S_FAILURE); 229113275Smike } 230113275Smike 231150652Scsjp maj_stat = KGSS_IMPORT(ctx, res.format, &res.interprocess_token); 232167309Spjd ctx->handle = 0; 233126023Snectar 234126023Snectar xdr_free((xdrproc_t) xdr_export_sec_context_res, &res); 235126023Snectar 236126023Snectar return (maj_stat); 237126023Snectar} 238126023Snectar 239126023Snectarvoid 240126023Snectarkgss_copy_buffer(const gss_buffer_t from, gss_buffer_t to) 241164032Srwatson{ 242126023Snectar to->length = from->length; 243126023Snectar if (from->length) { 244126023Snectar to->value = malloc(from->length, M_GSSAPI, M_WAITOK); 245113275Smike bcopy(from->value, to->value, from->length); 246168401Spjd } else { 247113275Smike to->value = NULL; 248113275Smike } 249168401Spjd} 250113275Smike 251113275Smike/* 252113275Smike * Kernel module glue 253113275Smike */ 254168401Spjdstatic int 255113275Smikekgssapi_modevent(module_t mod, int type, void *data) 256150652Scsjp{ 257113275Smike int error = 0; 258113275Smike 259113275Smike switch (type) { 260113275Smike case MOD_LOAD: 261172930Srwatson rpc_gss_entries.rpc_gss_secfind = rpc_gss_secfind; 262113275Smike rpc_gss_entries.rpc_gss_secpurge = rpc_gss_secpurge; 263113275Smike rpc_gss_entries.rpc_gss_seccreate = rpc_gss_seccreate; 264113275Smike rpc_gss_entries.rpc_gss_set_defaults = rpc_gss_set_defaults; 265113275Smike rpc_gss_entries.rpc_gss_max_data_length = 266150652Scsjp rpc_gss_max_data_length; 267113275Smike rpc_gss_entries.rpc_gss_get_error = rpc_gss_get_error; 26884828Sjhb rpc_gss_entries.rpc_gss_mech_to_oid = rpc_gss_mech_to_oid; 26984828Sjhb rpc_gss_entries.rpc_gss_oid_to_mech = rpc_gss_oid_to_mech; 27084828Sjhb rpc_gss_entries.rpc_gss_qop_to_num = rpc_gss_qop_to_num; 271113275Smike rpc_gss_entries.rpc_gss_get_mechanisms = rpc_gss_get_mechanisms; 27284828Sjhb rpc_gss_entries.rpc_gss_get_versions = rpc_gss_get_versions; 273113630Sjhb rpc_gss_entries.rpc_gss_is_installed = rpc_gss_is_installed; 27484828Sjhb rpc_gss_entries.rpc_gss_set_svc_name = rpc_gss_set_svc_name; 27584828Sjhb rpc_gss_entries.rpc_gss_clear_svc_name = rpc_gss_clear_svc_name; 27684828Sjhb rpc_gss_entries.rpc_gss_getcred = rpc_gss_getcred; 27746155Sphk rpc_gss_entries.rpc_gss_set_callback = rpc_gss_set_callback; 278113275Smike rpc_gss_entries.rpc_gss_clear_callback = rpc_gss_clear_callback; 279113275Smike rpc_gss_entries.rpc_gss_get_principal_name = 280150652Scsjp rpc_gss_get_principal_name; 281113275Smike rpc_gss_entries.rpc_gss_svc_max_data_length = 282113275Smike rpc_gss_svc_max_data_length; 283113275Smike break; 28446155Sphk case MOD_UNLOAD: 28546155Sphk /* 28646155Sphk * Unloading of the kgssapi module is not currently supported. 287113275Smike * If somebody wants this, we would need to keep track of 288113275Smike * currently executing threads and make sure the count is 0. 289113275Smike */ 290168399Spjd /* FALLTHROUGH */ 291113275Smike default: 292113275Smike error = EOPNOTSUPP; 293113275Smike }; 294113275Smike return (error); 295168401Spjd} 296113275Smikestatic moduledata_t kgssapi_mod = { 297113275Smike "kgssapi", 298113275Smike kgssapi_modevent, 299168489Spjd NULL, 300168489Spjd}; 301168489SpjdDECLARE_MODULE(kgssapi, kgssapi_mod, SI_SUB_VFS, SI_ORDER_ANY); 302168489SpjdMODULE_DEPEND(kgssapi, krpc, 1, 1, 1); 303113275SmikeMODULE_VERSION(kgssapi, 1); 304113275Smike