⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 authreg_ldap.c

📁 这是一个完全开放的
💻 C
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA *//* this plugin authenticates against an LDAP directory by attempting to bind * as the user. It won't store or retrieve any actual data, so only the * plaintext mechanism is available. * * !!! this doesn't do any caching. It really should. * * !!! this blocks for every auth. We're stuck with this until authreg can *     return a pending state. The timeout helps, but its still icky. */#include "c2s.h"#ifdef STORAGE_LDAP#include <lber.h>#include <ldap.h>#define AR_LDAP_FLAGS_STARTTLS  (0x1)#define AR_LDAP_FLAGS_SSL       (0x2)#define AR_LDAP_FLAGS_V3        (0x4)/** internal structure, holds our data */typedef struct moddata_st{    authreg_t ar;    LDAP *ld;    char *host;    long port;    int flags;    char *binddn;    char *bindpw;    char *uidattr;    xht basedn;    char *default_basedn;} *moddata_t;/** utility function to get ld_errno */static int _ldap_get_lderrno(LDAP *ld){    int ld_errno;    ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ld_errno);    return ld_errno;}/** connect to the ldap host */static int _ldap_connect(moddata_t data){    char url[1024];    int version = 2;    /* v3 */    if(data->flags & AR_LDAP_FLAGS_V3) {        version = 3;        /* starttls */        if(data->flags & AR_LDAP_FLAGS_STARTTLS) {            data->ld = ldap_init(data->host, data->port);            if(data->ld != NULL) {                if(ldap_set_option(data->ld, LDAP_OPT_PROTOCOL_VERSION, &version)) {                    log_write(data->ar->c2s->log, LOG_ERR, "ldap: couldn't use version 3: %s", ldap_err2string(_ldap_get_lderrno(data->ld)));                    ldap_unbind_s(data->ld);                    data->ld = NULL;                    return 1;                }                if(ldap_start_tls_s(data->ld, NULL, NULL)) {                    log_write(data->ar->c2s->log, LOG_ERR, "ldap: couldn't start TLS: %s", ldap_err2string(_ldap_get_lderrno(data->ld)));                    ldap_unbind_s(data->ld);                    data->ld = NULL;                    return 1;                }            }        }        /* ssl "wrappermode" */        else if(data->flags & AR_LDAP_FLAGS_SSL) {            snprintf(url, sizeof(url), "ldaps://%s:%ld", data->host, data->port);            ldap_initialize(&data->ld, url);        }        /* no frills */        else            data->ld = ldap_init(data->host, data->port);    }    /* v2 */    else        data->ld = ldap_init(data->host, data->port);    if(data->ld == NULL) {        log_write(data->ar->c2s->log, LOG_ERR, "ldap: connect to server at %s:%d failed", data->host, data->port);        return 1;    }    return 0;}/** do a search, return the dn */static char *_ldap_search(moddata_t data, char *realm, char *username){    char filter[1024], *dn, *no_attrs[] = { NULL }, *basedn;    LDAPMessage *result, *entry;    basedn = xhash_get(data->basedn, realm);    if(basedn == NULL)        basedn = data->default_basedn;    if(basedn == NULL) {        log_write(data->ar->c2s->log, LOG_ERR, "ldap: no basedn specified for realm '%s'", realm);        ldap_unbind_s(data->ld);        data->ld = NULL;        return NULL;    }    if(ldap_simple_bind_s(data->ld, data->binddn, data->bindpw)        && (_ldap_connect(data) || ldap_simple_bind_s(data->ld, data->binddn, data->bindpw)))     {        log_write(data->ar->c2s->log, LOG_ERR, "ldap: bind failed: %s", ldap_err2string(_ldap_get_lderrno(data->ld)));        ldap_unbind_s(data->ld);        data->ld = NULL;        return NULL;    }    snprintf(filter, 1024, "(%s=%s)", data->uidattr, username);    if(ldap_search_s(data->ld, basedn, LDAP_SCOPE_SUBTREE, filter, no_attrs, 0, &result))    {        log_write(data->ar->c2s->log, LOG_ERR, "ldap: search %s failed: %s", filter, ldap_err2string(_ldap_get_lderrno(data->ld)));        ldap_unbind_s(data->ld);        data->ld = NULL;        return NULL;    }    entry = ldap_first_entry(data->ld, result);    if(entry == NULL)    {        ldap_msgfree(result);        return NULL;    }    dn = ldap_get_dn(data->ld, entry);    ldap_msgfree(result);    log_debug(ZONE, "got dn '%s' from realm '%s', user '%s'", dn, realm, username);    return dn;}/** do we have this user? */static int _ldap_user_exists(authreg_t ar, char *username, char *realm){    char *dn;    int result;        moddata_t data = (moddata_t) ar->private;    if(data->ld == NULL && _ldap_connect(data))        return 0;        dn = _ldap_search(data, realm, username);    result = (int) dn;    ldap_memfree(dn);    return result;}/** check the password */static int _ldap_check_password(authreg_t ar, char *username, char *realm, char password[257]){    moddata_t data = (moddata_t) ar->private;    char *dn;    if(password[0] == '\0')        return 1;    if(data->ld == NULL && _ldap_connect(data))        return 1;    dn = _ldap_search(data, realm, username);    if(dn == NULL)        return 1;    if(ldap_simple_bind_s(data->ld, dn, password))    {        if(_ldap_get_lderrno(data->ld) != LDAP_INVALID_CREDENTIALS)        {            log_write(data->ar->c2s->log, LOG_ERR, "ldap: bind as '%s' failed: %s", dn, ldap_err2string(_ldap_get_lderrno(data->ld)));            ldap_unbind_s(data->ld);            data->ld = NULL;        }        ldap_memfree(dn);        return 1;    }    ldap_memfree(dn);    return 0;}/** shut me down */static void _ldap_free(authreg_t ar){    moddata_t data = (moddata_t) ar->private;    if(data->ld != NULL)        ldap_unbind_s(data->ld);    xhash_free(data->basedn);    free(data);    return;}/** start me up */int ar_ldap_init(authreg_t ar){    moddata_t data;    char *host, *realm;    config_elem_t basedn;    int i;    host = config_get_one(ar->c2s->config, "authreg.ldap.host", 0);    if(host == NULL)    {        log_write(ar->c2s->log, LOG_ERR, "ldap: no host specified in config file");        return 1;    }    basedn = config_get(ar->c2s->config, "authreg.ldap.basedn");    if(basedn == NULL)    {        log_write(ar->c2s->log, LOG_ERR, "ldap: no basedns specified in config file");        return 1;    }    data = (moddata_t) malloc(sizeof(struct moddata_st));    memset(data, 0, sizeof(struct moddata_st));    data->basedn = xhash_new(101);    for(i = 0; i < basedn->nvalues; i++)    {        realm = (basedn->attrs[i] != NULL) ? j_attr((const char **) basedn->attrs[i], "realm") : NULL;        if(realm == NULL)            data->default_basedn = basedn->values[i];        else            xhash_put(data->basedn, realm, basedn->values[i]);        log_debug(ZONE, "realm '%s' has base dn '%s'", realm, basedn->values[i]);    }    log_write(ar->c2s->log, LOG_NOTICE, "ldap: configured %d realms", i);    data->host = host;    data->port = j_atoi(config_get_one(ar->c2s->config, "authreg.ldap.port", 0), 389);    if(config_get(ar->c2s->config, "authreg.ldap.v3") != NULL) {        data->flags = AR_LDAP_FLAGS_V3;        if(config_get(ar->c2s->config, "authreg.ldap.starttls") != NULL)            data->flags |= AR_LDAP_FLAGS_STARTTLS;        if(config_get(ar->c2s->config, "authreg.ldap.ssl") != NULL)            data->flags |= AR_LDAP_FLAGS_SSL;    }    data->binddn = config_get_one(ar->c2s->config, "authreg.ldap.binddn", 0);    if(data->binddn != NULL)        data->bindpw = config_get_one(ar->c2s->config, "authreg.ldap.bindpw", 0);    data->uidattr = config_get_one(ar->c2s->config, "authreg.ldap.uidattr", 0);    if(data->uidattr == NULL)        data->uidattr = "uid";    data->ar = ar;        if(_ldap_connect(data))    {        xhash_free(data->basedn);        free(data);        return 1;    }    ar->private = data;    ar->user_exists = _ldap_user_exists;    ar->check_password = _ldap_check_password;    ar->free = _ldap_free;    return 0;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -