src/server/daemon/ldap_auth.c

Mon, 09 Sep 2013 12:15:54 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 09 Sep 2013 12:15:54 +0200
changeset 93
95b77e842db3
parent 91
fac51f87def0
child 97
09fbefc0e6a9
permissions
-rw-r--r--

fixed solaris build

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2013 Olaf Wintermann. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
 */

#ifdef __gnu_linux__
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "ldap_auth.h"

static void ws_ldap_close(LDAP *ldap) {
#ifdef SOLARIS
    ldap_unbind(ldap);
#else
    ldap_unbind_ext_s(ldap, NULL, NULL);
#endif
}

AuthDB* create_ldap_authdb(char *name, LDAPConfig *conf) {
    LDAPAuthDB *authdb = malloc(sizeof(LDAPAuthDB));
    authdb->authdb.name = strdup(name);
    authdb->authdb.get_user = ldap_get_user;
    authdb->authdb.use_cache = 1;
    authdb->config = *conf;

    if (!authdb->config.usersearch) {
        authdb->config.usersearch = "uid";
    }
    if (!authdb->config.groupsearch) {
        authdb->config.groupsearch = "uniquemember";
    }

    return (AuthDB*) authdb;
}

User* ldap_get_user(AuthDB *db, char *username) {
    LDAPAuthDB *authdb = (LDAPAuthDB*) db;
    LDAPConfig *config = &authdb->config;

    LDAP *ld = NULL;
#ifdef LINUX
    char *ldap_uri = NULL;
    asprintf(&ldap_uri, "ldap://%s:%d", config->hostname, config->port);
    int init_ret = ldap_initialize(&ld, ldap_uri);
    free(ldap_uri);
    if(init_ret) {
        fprintf(stderr, "ldap_initialize failed\n");
    }
    
#else
    ld = ldap_init(config->hostname, config->port);
#endif
    if (ld == NULL) {
        fprintf(stderr, "ldap_init failed\n");
        return NULL;
    }
    
    int ldapv = LDAP_VERSION3;
    ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapv);

    //int r = ldap_simple_bind_s(ld, config->binddn, config->bindpw);
    struct berval cred;
    cred.bv_val = config->bindpw;
    cred.bv_len = strlen(config->bindpw);
    struct berval *server_cred;
    int r = ldap_sasl_bind_s(
            ld,
            config->binddn,
            LDAP_SASL_SIMPLE,
            &cred,
            NULL,
            NULL,
            &server_cred);
    if (r != LDAP_SUCCESS) {
        ws_ldap_close(ld);
        
        fprintf(stderr, "ldap_simple_bind_s failed: %s\n", ldap_err2string(r));
        return NULL;
    }

    // get the user dn

    // TODO: use config for filter
    char filter[128];
    int s = snprintf(filter, 127, "uid=%s", username);
    filter[s] = 0;

    LDAPMessage *result;
    struct timeval timeout;
    timeout.tv_sec = 8;
    timeout.tv_usec = 0;
    r = ldap_search_ext_s(
            ld,
            config->basedn,
            LDAP_SCOPE_SUBTREE,
            filter,
            NULL,
            0,
            NULL,        // server controls
            NULL,        // client controls
            &timeout,
            1,           // size limit
            &result);
    if (r != LDAP_SUCCESS) {
        ws_ldap_close(ld);
        
        fprintf(stderr, "ldap_search_ext_s failed\n");
        return NULL;
    }

    LDAPMessage *msg = ldap_first_entry(ld, result);
    if (msg) {
        LDAPUser *user = malloc(sizeof(LDAPUser));
        if (user != NULL) {
            user->user.verify_password = ldap_user_verify_password;
            user->user.check_group = ldap_user_check_group;
            user->user.free = ldap_user_free;
            user->user.name = username; // must not be freed
            
            // TODO: get uid/gid from ldap
            user->user.uid = -1;
            user->user.gid = -1;

            user->ldap = ld;
            user->userdn = ldap_get_dn(ld, msg);

            ldap_msgfree(result);

            return (User*)user;
        }
    }

    ws_ldap_close(ld);
    return NULL;
}

int ldap_user_verify_password(User *u, char *password) {
    LDAPUser *user = (LDAPUser*)u;
    
    //int r = ldap_simple_bind_s(user->ldap, user->userdn, password);
    struct berval cred;
    cred.bv_val = password;
    cred.bv_len = strlen(password);
    struct berval *server_cred;
    int r = ldap_sasl_bind_s(
            user->ldap,
            user->userdn,
            LDAP_SASL_SIMPLE,
            &cred,
            NULL,
            NULL,
            &server_cred);
    if(r == LDAP_SUCCESS) {
        printf("ldap password ok\n");
        return 1;
    } else {
        printf("ldap password not ok\n");
        return 0;
    }
}

int ldap_user_check_group(User *user, char *group) {
    // TODO
    return 0;
}

void ldap_user_free(User *u) {
    LDAPUser *user = (LDAPUser*)u;
    ldap_memfree(user->userdn);
    // TODO: use connection pool
    ws_ldap_close(user->ldap);
    free(user);
}

mercurial