Blame src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c

Packit Service 99d1c0
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
Packit Service 99d1c0
/* plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c */
Packit Service 99d1c0
/*
Packit Service 99d1c0
 * Copyright (c) 2004-2005, Novell, Inc.
Packit Service 99d1c0
 * All rights reserved.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * Redistribution and use in source and binary forms, with or without
Packit Service 99d1c0
 * modification, are permitted provided that the following conditions are met:
Packit Service 99d1c0
 *
Packit Service 99d1c0
 *   * Redistributions of source code must retain the above copyright notice,
Packit Service 99d1c0
 *       this list of conditions and the following disclaimer.
Packit Service 99d1c0
 *   * Redistributions in binary form must reproduce the above copyright
Packit Service 99d1c0
 *       notice, this list of conditions and the following disclaimer in the
Packit Service 99d1c0
 *       documentation and/or other materials provided with the distribution.
Packit Service 99d1c0
 *   * The copyright holder's name is not used to endorse or promote products
Packit Service 99d1c0
 *       derived from this software without specific prior written permission.
Packit Service 99d1c0
 *
Packit Service 99d1c0
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit Service 99d1c0
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 99d1c0
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit Service 99d1c0
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
Packit Service 99d1c0
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit Service 99d1c0
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit Service 99d1c0
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit Service 99d1c0
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
Packit Service 99d1c0
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
Packit Service 99d1c0
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Packit Service 99d1c0
 * POSSIBILITY OF SUCH DAMAGE.
Packit Service 99d1c0
 */
Packit Service 99d1c0
Packit Service 99d1c0
#include "autoconf.h"
Packit Service 99d1c0
#if HAVE_UNISTD_H
Packit Service 99d1c0
#include <unistd.h>
Packit Service 99d1c0
#endif
Packit Service 99d1c0
Packit Service 99d1c0
#include <ctype.h>
Packit Service 99d1c0
#include "kdb_ldap.h"
Packit Service 99d1c0
#include "ldap_misc.h"
Packit Service 99d1c0
#include <kdb5.h>
Packit Service 99d1c0
#include <kadm5/admin.h>
Packit Service 99d1c0
Packit Service 99d1c0
/*
Packit Service 99d1c0
 * ldap get age
Packit Service 99d1c0
 */
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krb5_ldap_get_age(context, db_name, age)
Packit Service 99d1c0
    krb5_context context;
Packit Service 99d1c0
    char *db_name;
Packit Service 99d1c0
    time_t *age;
Packit Service 99d1c0
{
Packit Service 99d1c0
    time (age);
Packit Service 99d1c0
    return 0;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
/*
Packit Service 99d1c0
 * read startup information - kerberos and realm container
Packit Service 99d1c0
 */
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krb5_ldap_read_startup_information(krb5_context context)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code      retval = 0;
Packit Service 99d1c0
    kdb5_dal_handle      *dal_handle=NULL;
Packit Service 99d1c0
    krb5_ldap_context    *ldap_context=NULL;
Packit Service 99d1c0
    int                  mask = 0;
Packit Service 99d1c0
Packit Service 99d1c0
    SETUP_CONTEXT();
Packit Service 99d1c0
    if ((retval=krb5_ldap_read_krbcontainer_dn(context, &(ldap_context->container_dn)))) {
Packit Service 99d1c0
        k5_prependmsg(context, retval, _("Unable to read Kerberos container"));
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if ((retval=krb5_ldap_read_realm_params(context, context->default_realm, &(ldap_context->lrparams), &mask))) {
Packit Service 99d1c0
        k5_prependmsg(context, retval, _("Unable to read Realm"));
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if (((mask & LDAP_REALM_MAXTICKETLIFE) == 0) || ((mask & LDAP_REALM_MAXRENEWLIFE) == 0)
Packit Service 99d1c0
        || ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0)) {
Packit Service 99d1c0
        kadm5_config_params  params_in, params_out;
Packit Service 99d1c0
Packit Service 99d1c0
        memset(&params_in, 0, sizeof(params_in));
Packit Service 99d1c0
        memset(&params_out, 0, sizeof(params_out));
Packit Service 99d1c0
Packit Service 99d1c0
        retval = kadm5_get_config_params(context, 1, &params_in, &params_out);
Packit Service 99d1c0
        if (retval) {
Packit Service 99d1c0
            if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
Packit Service 99d1c0
                ldap_context->lrparams->max_life = 24 * 60 * 60; /* 1 day */
Packit Service 99d1c0
            }
Packit Service 99d1c0
            if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
Packit Service 99d1c0
                ldap_context->lrparams->max_renewable_life = 0;
Packit Service 99d1c0
            }
Packit Service 99d1c0
            if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
Packit Service 99d1c0
                ldap_context->lrparams->tktflags = KRB5_KDB_DEF_FLAGS;
Packit Service 99d1c0
            }
Packit Service 99d1c0
            retval = 0;
Packit Service 99d1c0
            goto cleanup;
Packit Service 99d1c0
        }
Packit Service 99d1c0
Packit Service 99d1c0
        if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
Packit Service 99d1c0
            if (params_out.mask & KADM5_CONFIG_MAX_LIFE)
Packit Service 99d1c0
                ldap_context->lrparams->max_life = params_out.max_life;
Packit Service 99d1c0
        }
Packit Service 99d1c0
Packit Service 99d1c0
        if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) {
Packit Service 99d1c0
            if (params_out.mask & KADM5_CONFIG_MAX_RLIFE)
Packit Service 99d1c0
                ldap_context->lrparams->max_renewable_life = params_out.max_rlife;
Packit Service 99d1c0
        }
Packit Service 99d1c0
Packit Service 99d1c0
        if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) {
Packit Service 99d1c0
            if (params_out.mask & KADM5_CONFIG_FLAGS)
Packit Service 99d1c0
                ldap_context->lrparams->tktflags = params_out.flags;
Packit Service 99d1c0
        }
Packit Service 99d1c0
Packit Service 99d1c0
        kadm5_free_config_params(context, &params_out);
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
cleanup:
Packit Service 99d1c0
    return retval;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
Packit Service 99d1c0
/* Interrogate the root DSE (zero length DN) for an attribute value assertion.
Packit Service 99d1c0
 * Return true if it is present, false if it is absent or we can't tell. */
Packit Service 99d1c0
static krb5_boolean
Packit Service 99d1c0
has_rootdse_ava(krb5_context context, const char *server_name,
Packit Service 99d1c0
                const char *attribute, const char *value)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_boolean result = FALSE;
Packit Service 99d1c0
    char *attrs[2], **values = NULL;
Packit Service 99d1c0
    int i, st;
Packit Service 99d1c0
    LDAP *ld = NULL;
Packit Service 99d1c0
    LDAPMessage *msg, *res = NULL;
Packit Service 99d1c0
    struct berval cred;
Packit Service 99d1c0
Packit Service 99d1c0
    attrs[0] = (char *)attribute;
Packit Service 99d1c0
    attrs[1] = NULL;
Packit Service 99d1c0
Packit Service 99d1c0
    st = ldap_initialize(&ld, server_name);
Packit Service 99d1c0
    if (st != LDAP_SUCCESS)
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
    /* Bind anonymously. */
Packit Service 99d1c0
    cred.bv_val = "";
Packit Service 99d1c0
    cred.bv_len = 0;
Packit Service 99d1c0
    st = ldap_sasl_bind_s(ld, "", NULL, &cred, NULL, NULL, NULL);
Packit Service 99d1c0
    if (st != LDAP_SUCCESS)
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
    st = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, NULL,
Packit Service 99d1c0
                           NULL, NULL, 0, &res;;
Packit Service 99d1c0
    if (st != LDAP_SUCCESS)
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
    msg = ldap_first_message(ld, res);
Packit Service 99d1c0
    if (msg == NULL)
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
    values = ldap_get_values(ld, msg, attribute);
Packit Service 99d1c0
    if (values == NULL)
Packit Service 99d1c0
        goto cleanup;
Packit Service 99d1c0
Packit Service 99d1c0
    for (i = 0; values[i] != NULL; i++) {
Packit Service 99d1c0
        if (strcmp(values[i], value) == 0) {
Packit Service 99d1c0
            result = TRUE;
Packit Service 99d1c0
            goto cleanup;
Packit Service 99d1c0
        }
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
cleanup:
Packit Service 99d1c0
    ldap_value_free(values);
Packit Service 99d1c0
    ldap_msgfree(res);
Packit Service 99d1c0
    ldap_unbind_ext_s(ld, NULL, NULL);
Packit Service 99d1c0
Packit Service 99d1c0
    return result;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_boolean
Packit Service 99d1c0
has_modify_increment(krb5_context context, const char *server_name)
Packit Service 99d1c0
{
Packit Service 99d1c0
    return has_rootdse_ava(context, server_name, "supportedFeatures",
Packit Service 99d1c0
                           "1.3.6.1.1.14");
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
void *
Packit Service 99d1c0
krb5_ldap_alloc(krb5_context context, void *ptr, size_t size)
Packit Service 99d1c0
{
Packit Service 99d1c0
    return realloc(ptr, size);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
void
Packit Service 99d1c0
krb5_ldap_free(krb5_context context, void *ptr)
Packit Service 99d1c0
{
Packit Service 99d1c0
    free(ptr);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krb5_ldap_open(krb5_context context, char *conf_section, char **db_args,
Packit Service 99d1c0
               int mode)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code status  = 0;
Packit Service 99d1c0
    krb5_ldap_context *ldap_context=NULL;
Packit Service 99d1c0
Packit Service 99d1c0
    /* Clear the global error string */
Packit Service 99d1c0
    krb5_clear_error_message(context);
Packit Service 99d1c0
Packit Service 99d1c0
    ldap_context = k5alloc(sizeof(krb5_ldap_context), &status);
Packit Service 99d1c0
    if (ldap_context == NULL)
Packit Service 99d1c0
        goto clean_n_exit;
Packit Service 99d1c0
    context->dal_handle->db_context = ldap_context;
Packit Service 99d1c0
    ldap_context->kcontext = context;
Packit Service 99d1c0
Packit Service 99d1c0
    status = krb5_ldap_parse_db_params(context, db_args);
Packit Service 99d1c0
    if (status) {
Packit Service 99d1c0
        k5_prependmsg(context, status, _("Error processing LDAP DB params"));
Packit Service 99d1c0
        goto clean_n_exit;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    status = krb5_ldap_read_server_params(context, conf_section, mode & 0x0300);
Packit Service 99d1c0
    if (status) {
Packit Service 99d1c0
        k5_prependmsg(context, status, _("Error reading LDAP server params"));
Packit Service 99d1c0
        goto clean_n_exit;
Packit Service 99d1c0
    }
Packit Service 99d1c0
    if ((status=krb5_ldap_db_init(context, ldap_context)) != 0) {
Packit Service 99d1c0
        goto clean_n_exit;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    if ((status=krb5_ldap_read_startup_information(context)) != 0) {
Packit Service 99d1c0
        goto clean_n_exit;
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
clean_n_exit:
Packit Service 99d1c0
    /* may be clearing up is not required  db_fini might do it for us, check out */
Packit Service 99d1c0
    if (status) {
Packit Service 99d1c0
        krb5_ldap_close(context);
Packit Service 99d1c0
    }
Packit Service 99d1c0
    return status;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
#include "ldap_err.h"
Packit Service 99d1c0
int
Packit Service 99d1c0
set_ldap_error(krb5_context ctx, int st, int op)
Packit Service 99d1c0
{
Packit Service 99d1c0
    int translated_st = translate_ldap_error(st, op);
Packit Service 99d1c0
    k5_setmsg(ctx, translated_st, "%s", ldap_err2string(st));
Packit Service 99d1c0
    return translated_st;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
extern krb5int_access accessor;
Packit Service 99d1c0
MAKE_INIT_FUNCTION(kldap_init_fn);
Packit Service 99d1c0
Packit Service 99d1c0
int
Packit Service 99d1c0
kldap_init_fn(void)
Packit Service 99d1c0
{
Packit Service 99d1c0
    /* Global (per-module) initialization.  */
Packit Service 99d1c0
    return krb5int_accessor (&accessor, KRB5INT_ACCESS_VERSION);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
int
Packit Service 99d1c0
kldap_ensure_initialized(void)
Packit Service 99d1c0
{
Packit Service 99d1c0
    return CALL_INIT_FUNCTION (kldap_init_fn);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request,
Packit Service 99d1c0
                          krb5_db_entry *client, krb5_db_entry *server,
Packit Service 99d1c0
                          krb5_timestamp kdc_time, const char **status,
Packit Service 99d1c0
                          krb5_pa_data ***e_data)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code retval;
Packit Service 99d1c0
Packit Service 99d1c0
    retval = krb5_ldap_lockout_check_policy(kcontext, client, kdc_time);
Packit Service 99d1c0
    if (retval == KRB5KDC_ERR_CLIENT_REVOKED)
Packit Service 99d1c0
        *status = "LOCKED_OUT";
Packit Service 99d1c0
    return retval;
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
void
Packit Service 99d1c0
krb5_ldap_audit_as_req(krb5_context kcontext, krb5_kdc_req *request,
Packit Service 99d1c0
                       const krb5_address *local_addr,
Packit Service 99d1c0
                       const krb5_address *remote_addr, krb5_db_entry *client,
Packit Service 99d1c0
                       krb5_db_entry *server, krb5_timestamp authtime,
Packit Service 99d1c0
                       krb5_error_code error_code)
Packit Service 99d1c0
{
Packit Service 99d1c0
    (void) krb5_ldap_lockout_audit(kcontext, client, authtime, error_code);
Packit Service 99d1c0
}
Packit Service 99d1c0
Packit Service 99d1c0
krb5_error_code
Packit Service 99d1c0
krb5_ldap_check_allowed_to_delegate(krb5_context context,
Packit Service 99d1c0
                                    krb5_const_principal client,
Packit Service 99d1c0
                                    const krb5_db_entry *server,
Packit Service 99d1c0
                                    krb5_const_principal proxy)
Packit Service 99d1c0
{
Packit Service 99d1c0
    krb5_error_code code;
Packit Service 99d1c0
    krb5_tl_data *tlp;
Packit Service 99d1c0
Packit Service 99d1c0
    code = KRB5KDC_ERR_POLICY;
Packit Service 99d1c0
Packit Service 99d1c0
    for (tlp = server->tl_data; tlp != NULL; tlp = tlp->tl_data_next) {
Packit Service 99d1c0
        krb5_principal acl;
Packit Service 99d1c0
Packit Service 99d1c0
        if (tlp->tl_data_type != KRB5_TL_CONSTRAINED_DELEGATION_ACL)
Packit Service 99d1c0
            continue;
Packit Service 99d1c0
Packit Service 99d1c0
        if (krb5_parse_name(context, (char *)tlp->tl_data_contents, &acl) != 0)
Packit Service 99d1c0
            continue;
Packit Service 99d1c0
Packit Service 99d1c0
        if (krb5_principal_compare(context, proxy, acl)) {
Packit Service 99d1c0
            code = 0;
Packit Service 99d1c0
            krb5_free_principal(context, acl);
Packit Service 99d1c0
            break;
Packit Service 99d1c0
        }
Packit Service 99d1c0
        krb5_free_principal(context, acl);
Packit Service 99d1c0
    }
Packit Service 99d1c0
Packit Service 99d1c0
    return code;
Packit Service 99d1c0
}