smbd_krb5ssp.c revision 12b65585e720714b31036daaa2b30eb76014048e
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * This file and its contents are supplied under the terms of the
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * You may only use this file in accordance with the terms of version
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * 1.0 of the CDDL.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * A full copy of the text of the CDDL should have accompanied this
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * source. A copy of the CDDL is also available via the Internet at
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * http://www.illumos.org/license/CDDL.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * SPNEGO back-end for Kerberos. See [MS-KILE]
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <sys/types.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <gssapi/gssapi_ext.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <gssapi/gssapi_krb5.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include <krb5.h>
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include "smbd.h"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#include "smbd_authsvc.h"
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/* From krb5/krb/pac.c (should have been exported) */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross#define PAC_LOGON_INFO 1
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rosstypedef struct krb5ssp_backend {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_ctx_id_t be_gssctx;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross char *be_username;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_desc be_authz_pac;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_context be_kctx;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_pac be_kpac;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_data be_pac;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross} krb5ssp_backend_t;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic uint32_t
12b65585e720714b31036daaa2b30eb76014048eGordon Rossget_authz_data_pac(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_ctx_id_t context_handle,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_t ad_data);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic uint32_t
12b65585e720714b31036daaa2b30eb76014048eGordon Rossget_ssnkey(authsvc_context_t *ctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Initialize this context for Kerberos, if possible.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Should not get here unless libsmb smb_config_get_negtok
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * includes the Kerberos5 Mech OIDs in our spnego hint.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Todo: allocate ctx->ctx_backend
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: krb5_gss_accept_sec_context()
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_krb5ssp_init(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5ssp_backend_t *be;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be = malloc(sizeof (*be));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_NO_MEMORY);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(be, sizeof (*be));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->be_gssctx = GSS_C_NO_CONTEXT;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_backend = be;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Todo: free ctx->ctx_backend
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossvoid
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_krb5ssp_fini(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5ssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t minor;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be == NULL)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->be_kctx != NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_free_data_contents(be->be_kctx, &be->be_pac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->be_kpac != NULL)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_pac_free(be->be_kctx, be->be_kpac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_free_context(be->be_kctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_release_buffer(NULL, &be->be_authz_pac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross free(be->be_username);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->be_gssctx != GSS_C_NO_CONTEXT) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_delete_sec_context(&minor, &be->be_gssctx,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross GSS_C_NO_BUFFER);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross free(be);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Handle a Kerberos auth message.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * State across messages is in ctx->ctx_backend
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossint
12b65585e720714b31036daaa2b30eb76014048eGordon Rosssmbd_krb5ssp_work(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_desc intok, outtok;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_desc namebuf;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5ssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_name_t gname = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross OM_uint32 major, minor, ret_flags;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_OID name_type = GSS_C_NULL_OID;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_OID mech_type = GSS_C_NULL_OID;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_error_code kerr;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t status;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross intok.length = ctx->ctx_ibodylen;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross intok.value = ctx->ctx_ibodybuf;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(&outtok, sizeof (gss_buffer_desc));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bzero(&namebuf, sizeof (gss_buffer_desc));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Do this early, for error message support. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross kerr = krb5_init_context(&be->be_kctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (kerr != 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp, krb5_init_ctx: %s",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_get_error_message(be->be_kctx, kerr));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_INTERNAL_ERROR);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross major = gss_accept_sec_context(&minor, &be->be_gssctx,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross GSS_C_NO_CREDENTIAL, &intok,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross GSS_C_NO_CHANNEL_BINDINGS, &gname, &mech_type, &outtok,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &ret_flags, NULL, NULL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (outtok.length == 0)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodylen = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross else if (outtok.length <= ctx->ctx_obodylen) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodylen = outtok.length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) memcpy(ctx->ctx_obodybuf, outtok.value, outtok.length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross free(outtok.value);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross outtok.value = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross } else {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross free(ctx->ctx_obodybuf);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodybuf = outtok.value;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_obodylen = outtok.length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross outtok.value = NULL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (GSS_ERROR(major)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp: gss_accept_sec_context, "
12b65585e720714b31036daaa2b30eb76014048eGordon Ross "mech=0x%x, major=0x%x, minor=0x%x",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (int)mech_type, major, minor);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report(" krb5: %s",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_get_error_message(be->be_kctx, minor));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_WRONG_PASSWORD);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross switch (major) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross case GSS_S_COMPLETE:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross break;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross case GSS_S_CONTINUE_NEEDED:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (outtok.length > 0) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_orawtype = LSA_MTYPE_ES_CONT;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* becomes NT_STATUS_MORE_PROCESSING_REQUIRED */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_WRONG_PASSWORD);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross default:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_WRONG_PASSWORD);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * OK, we got GSS_S_COMPLETE. Get the name so we can use it
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * in log messages if we get failures decoding the PAC etc.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Then get the PAC, decode it, build the logon token.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (gname != NULL && GSS_S_COMPLETE ==
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_display_name(&minor, gname, &namebuf, &name_type)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Save the user name. */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->be_username = strdup(namebuf.value);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_release_buffer(&minor, &namebuf);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_release_name(&minor, &gname);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (be->be_username == NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_NO_MEMORY);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Extract the KRB5_AUTHDATA_WIN2K_PAC data.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = get_authz_data_pac(be->be_gssctx,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &be->be_authz_pac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (status)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross kerr = krb5_pac_parse(be->be_kctx, be->be_authz_pac.value,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->be_authz_pac.length, &be->be_kpac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (kerr) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp, krb5_pac_parse: %s",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_get_error_message(be->be_kctx, kerr));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_UNSUCCESSFUL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross kerr = krb5_pac_get_buffer(be->be_kctx, be->be_kpac,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross PAC_LOGON_INFO, &be->be_pac);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (kerr) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp, krb5_pac_get_buffer: %s",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5_get_error_message(be->be_kctx, kerr));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_UNSUCCESSFUL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_token = calloc(1, sizeof (smb_token_t));
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ctx->ctx_token == NULL)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_NO_MEMORY);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = smb_decode_krb5_pac(ctx->ctx_token, be->be_pac.data,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->be_pac.length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (status)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = get_ssnkey(ctx);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (status)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (!smb_token_setup_common(ctx->ctx_token))
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (NT_STATUS_UNSUCCESSFUL);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Success! */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_orawtype = LSA_MTYPE_ES_DONE;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (0);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * and: KRB5_AUTHDATA_WIN2K_PAC
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic const gss_OID_desc
12b65585e720714b31036daaa2b30eb76014048eGordon Rossoid_ex_authz_data_pac = {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross 13, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a\x81\x00" };
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: krb5_gss_inquire_sec_context_by_oid()
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * and krb5_gss_inquire_sec_context_by_oid_ops[],
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * gss_krb5int_extract_authz_data_from_sec_context()
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic uint32_t
12b65585e720714b31036daaa2b30eb76014048eGordon Rossget_authz_data_pac(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_ctx_id_t context_handle,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_t ad_data)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross OM_uint32 major, minor;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t status = NT_STATUS_UNSUCCESSFUL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ad_data == NULL)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross major = gss_inquire_sec_context_by_oid(
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &minor,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross context_handle,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (gss_OID)&oid_ex_authz_data_pac,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross &data_set);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (GSS_ERROR(major)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp, gss_inquire...PAC, "
12b65585e720714b31036daaa2b30eb76014048eGordon Ross "major=0x%x, minor=0x%x", major, minor);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((data_set == GSS_C_NO_BUFFER_SET) || (data_set->count == 0)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /* Only need the first element? */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ad_data->length = data_set->elements[0].length;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ad_data->value = malloc(ad_data->length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ad_data->value == NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = NT_STATUS_NO_MEMORY;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bcopy(data_set->elements[0].value, ad_data->value, ad_data->length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossout:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_release_buffer_set(&minor, &data_set);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross/*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * Get the session key, and save it in the token.
12b65585e720714b31036daaa2b30eb76014048eGordon Ross *
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * See: krb5_gss_inquire_sec_context_by_oid(),
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * krb5_gss_inquire_sec_context_by_oid_ops[], and
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * gss_krb5int_inq_session_key
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Rossstatic uint32_t
12b65585e720714b31036daaa2b30eb76014048eGordon Rossget_ssnkey(authsvc_context_t *ctx)
12b65585e720714b31036daaa2b30eb76014048eGordon Ross{
12b65585e720714b31036daaa2b30eb76014048eGordon Ross krb5ssp_backend_t *be = ctx->ctx_backend;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross OM_uint32 major, minor;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross size_t keylen;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross uint32_t status = NT_STATUS_UNSUCCESSFUL;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross major = gss_inquire_sec_context_by_oid(&minor,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross be->be_gssctx, GSS_C_INQ_SSPI_SESSION_KEY, &data_set);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (GSS_ERROR(major)) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp, failed to get session key, "
12b65585e720714b31036daaa2b30eb76014048eGordon Ross "major=0x%x, minor=0x%x", major, minor);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross /*
12b65585e720714b31036daaa2b30eb76014048eGordon Ross * The key is in the first element
12b65585e720714b31036daaa2b30eb76014048eGordon Ross */
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (data_set == GSS_C_NO_BUFFER_SET ||
12b65585e720714b31036daaa2b30eb76014048eGordon Ross data_set->count == 0 ||
12b65585e720714b31036daaa2b30eb76014048eGordon Ross data_set->elements[0].length == 0 ||
12b65585e720714b31036daaa2b30eb76014048eGordon Ross data_set->elements[0].value == NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp: Session key is missing");
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if ((keylen = data_set->elements[0].length) < SMBAUTH_HASH_SZ) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross smbd_report("krb5ssp: Session key too short (%d)",
12b65585e720714b31036daaa2b30eb76014048eGordon Ross data_set->elements[0].length);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_token->tkn_ssnkey.val = malloc(keylen);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross if (ctx->ctx_token->tkn_ssnkey.val == NULL) {
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = NT_STATUS_NO_MEMORY;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross goto out;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross }
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_token->tkn_ssnkey.len = keylen;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross bcopy(data_set->elements[0].value,
12b65585e720714b31036daaa2b30eb76014048eGordon Ross ctx->ctx_token->tkn_ssnkey.val, keylen);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross status = 0;
12b65585e720714b31036daaa2b30eb76014048eGordon Ross
12b65585e720714b31036daaa2b30eb76014048eGordon Rossout:
12b65585e720714b31036daaa2b30eb76014048eGordon Ross (void) gss_release_buffer_set(&minor, &data_set);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross return (status);
12b65585e720714b31036daaa2b30eb76014048eGordon Ross}