/* * ctx.c * * Copyright (c) 2004 The Regents of the University of Michigan. * All rights reserved. * * Copyright (c) 2004 Marius Aamodt Eriksen . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: ctx.c,v 1.4 2004/06/14 19:38:56 marius Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpcd.h" static int _ctxcompare(struct rpcd_ctx *, struct rpcd_ctx *); static SPLAY_HEAD(ctxtree, rpcd_ctx) _ctxs; SPLAY_PROTOTYPE(ctxtree, rpcd_ctx, ctx_node, _ctxcompare); SPLAY_GENERATE(ctxtree, rpcd_ctx, ctx_node, _ctxcompare); void ctx_init(void) { SPLAY_INIT(&_ctxs); } /* * TODO: * * - keep tailq of per-mount, so that we can easily free each * ctx that belongs to a certain mntpoint. */ struct rpcd_ctx * ctx_get(uid_t uid, char *export, char *mount) { struct rpcd_ctx *ctx, searchctx; char *p, *host; if (set_krb5_ccache(uid) < 0) return (NULL); searchctx.ctx_uid = uid; strlcpy(searchctx.ctx_svc_export, export, sizeof(searchctx.ctx_svc_export)); strlcpy(searchctx.ctx_mntpt, mount, sizeof(searchctx.ctx_mntpt)); if ((ctx = SPLAY_FIND(ctxtree, &_ctxs, &searchctx)) != NULL) return (ctx); if ((ctx = malloc(sizeof(*ctx))) == NULL) return (NULL); *ctx = searchctx; host = export; p = strchr(host, ':'); if (p != NULL) *p = '\0'; if ((ctx->ctx_host = strdup(host)) == NULL) { free(ctx); return (NULL); } if (ctx_refresh(ctx) < 0) { free(ctx); return (NULL); } SPLAY_INSERT(ctxtree, &_ctxs, ctx); return (ctx); } int ctx_refresh(struct rpcd_ctx *ctx) { char svchost[128]; struct rpc_gss_sec sec; AUTH *auth; ctx->ctx_clnt = clnt_create(ctx->ctx_host, 100003, 4, "tcp"); if (ctx->ctx_clnt == NULL) { warnx("Cannot create rpcclnt for %s", ctx->ctx_host); return (NULL); } snprintf(svchost, sizeof(svchost), "nfs@%s", ctx->ctx_host); sec.mech = (gss_OID)&krb5oid; sec.qop = GSS_C_QOP_DEFAULT; sec.svc = RPCSEC_GSS_SVC_NONE; if ((auth = authgss_create_default(ctx->ctx_clnt, svchost, &sec)) == NULL) { warnx("Failed to initialize context for user %d", ctx->ctx_uid); clnt_destroy(ctx->ctx_clnt); return (-1); } ctx->ctx_clnt->cl_auth = auth; if (!authgss_service(ctx->ctx_clnt->cl_auth, RPCSEC_GSS_SVC_INTEGRITY)) warnx("Failed to initialize integrity for user %d", ctx->ctx_uid); return (0); } void ctx_put(struct rpcd_ctx *ctx) { SPLAY_REMOVE(ctxtree, &_ctxs, ctx); free(ctx); } static int _ctxcompare(struct rpcd_ctx *ctx0, struct rpcd_ctx *ctx1) { int diff; diff = ctx0->ctx_uid - ctx1->ctx_uid; if (diff != 0) return (diff); diff = strcmp(ctx0->ctx_svc_export, ctx1->ctx_svc_export); if (diff != 0) return (diff); return (strcmp(ctx0->ctx_mntpt, ctx1->ctx_mntpt)); }