📄 rlm_ldap.c
字号:
return RLM_MODULE_INVALID; } /* * Check that we don't have any failed connections. If we do there's no real need * of runing. Also give it another chance if we have a lot of failed connections. */ if (inst->failed_conns > MAX_FAILED_CONNS_END) inst->failed_conns = 0; if (inst->failed_conns > MAX_FAILED_CONNS_START){ inst->failed_conns++; return RLM_MODULE_FAIL; } DEBUG("rlm_ldap: login attempt by \"%s\" with password \"%s\"", request->username->strvalue, request->password->strvalue); while((vp_user_dn = pairfind(request->packet->vps, PW_LDAP_USERDN)) == NULL) { if (!radius_xlat(filter, sizeof(filter), inst->filter, request, NULL)) { radlog (L_ERR, "rlm_ldap: unable to create filter.\n"); return RLM_MODULE_INVALID; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, request, NULL)) { radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); return RLM_MODULE_INVALID; } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); return RLM_MODULE_FAIL; } if ((res = perform_search(instance, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) != RLM_MODULE_OK) { if (res == RLM_MODULE_NOTFOUND){ snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: User not found"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); } ldap_release_conn(conn_id,inst->conns); return (res); } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_FAIL; } if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) { DEBUG("rlm_ldap: ldap_get_dn() failed"); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_FAIL; } ldap_release_conn(conn_id,inst->conns); pairadd(&request->packet->vps, pairmake("Ldap-UserDn", user_dn, T_OP_EQ)); ldap_memfree(user_dn); ldap_msgfree(result); } user_dn = vp_user_dn->strvalue; DEBUG("rlm_ldap: user DN: %s", user_dn); ld_user = ldap_connect(instance, user_dn, request->password->strvalue, 1, &res); if (ld_user == NULL){ if (res == RLM_MODULE_REJECT){ inst->failed_conns = 0; snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Bind as user failed"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); } if (res == RLM_MODULE_FAIL){ DEBUG("rlm_ldap: ldap_connect() failed"); inst->failed_conns++; } return (res); } DEBUG("rlm_ldap: user %s authenticated succesfully", request->username->strvalue); ldap_unbind_s(ld_user); inst->failed_conns = 0; return RLM_MODULE_OK;}static LDAP *ldap_connect(void *instance, const char *dn, const char *password, int auth, int *result){ ldap_instance *inst = instance; LDAP *ld = NULL; int msgid, rc, ldap_version; int ldap_errno = 0; LDAPMessage *res; if (inst->is_url){#ifdef HAVE_LDAP_INITIALIZE DEBUG("rlm_ldap: (re)connect to %s, authentication %d", inst->server, auth); if (ldap_initialize(&ld, inst->server) != LDAP_SUCCESS) { radlog(L_ERR, "rlm_ldap: ldap_initialize() failed"); *result = RLM_MODULE_FAIL; return (NULL); }#endif } else{ DEBUG("rlm_ldap: (re)connect to %s:%d, authentication %d", inst->server, inst->port, auth); if ((ld = ldap_init(inst->server, inst->port)) == NULL) { radlog(L_ERR, "rlm_ldap: ldap_init() failed"); *result = RLM_MODULE_FAIL; return (NULL); } } if (ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, (void *) &(inst->net_timeout)) != LDAP_OPT_SUCCESS) { radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_NETWORK_TIMEOUT %ld.%ld", inst->net_timeout.tv_sec, inst->net_timeout.tv_usec); } if (ldap_set_option(ld, LDAP_OPT_TIMELIMIT, (void *) &(inst->timelimit)) != LDAP_OPT_SUCCESS) { radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_TIMELIMIT %d", inst->timelimit); } if (inst->ldap_debug && ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &(inst->ldap_debug)) != LDAP_OPT_SUCCESS) { radlog(L_ERR, "rlm_ldap: Could not set LDAP_OPT_DEBUG_LEVEL %d", inst->ldap_debug); } ldap_version = LDAP_VERSION3; if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldap_version) != LDAP_OPT_SUCCESS) { radlog(L_ERR, "rlm_ldap: Could not set LDAP version to V3"); }#ifdef HAVE_LDAP_START_TLS if(inst->tls_mode) { DEBUG("rlm_ldap: setting TLS mode to %d", inst->tls_mode); if(ldap_set_option(ld, LDAP_OPT_X_TLS, (void *) &(inst->tls_mode)) != LDAP_OPT_SUCCESS) { ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); radlog(L_ERR, "rlm_ldap: could not set LDAP_OPT_X_TLS option %s", ldap_err2string(ldap_errno)); } } if (inst->start_tls) { DEBUG("rlm_ldap: starting TLS"); rc = ldap_start_tls_s(ld, NULL, NULL); if (rc != LDAP_SUCCESS) { DEBUG("rlm_ldap: ldap_start_tls_s()"); ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); radlog(L_ERR, "rlm_ldap: could not start TLS %s", ldap_err2string(ldap_errno)); *result = RLM_MODULE_FAIL; ldap_unbind_s(ld); return (NULL); } }#endif /* HAVE_LDAP_START_TLS */ if (inst->is_url){ DEBUG("rlm_ldap: bind as %s/%s to %s", dn, password, inst->server); } else{ DEBUG("rlm_ldap: bind as %s/%s to %s:%d", dn, password, inst->server, inst->port); } msgid = ldap_bind(ld, dn, password,LDAP_AUTH_SIMPLE); if (msgid == -1) { ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); if (inst->is_url) radlog(L_ERR, "rlm_ldap: %s bind to %s failed: %s", dn, inst->server, ldap_err2string(ldap_errno)); else radlog(L_ERR, "rlm_ldap: %s bind to %s:%d failed: %s", dn, inst->server, inst->port, ldap_err2string(ldap_errno)); *result = RLM_MODULE_FAIL; ldap_unbind_s(ld); return (NULL); } DEBUG("rlm_ldap: waiting for bind result ..."); rc = ldap_result(ld, msgid, 1, &(inst->timeout), &res); if(rc < 1) { DEBUG("rlm_ldap: ldap_result()"); ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); if (inst->is_url) radlog(L_ERR, "rlm_ldap: %s bind to %s failed: %s", dn, inst->server, (rc == 0) ? "timeout" : ldap_err2string(ldap_errno)); else radlog(L_ERR, "rlm_ldap: %s bind to %s:%d failed: %s", dn, inst->server, inst->port, (rc == 0) ? "timeout" : ldap_err2string(ldap_errno)); *result = RLM_MODULE_FAIL; ldap_unbind_s(ld); return (NULL); } ldap_errno = ldap_result2error(ld, res, 1); switch (ldap_errno) { case LDAP_SUCCESS: *result = RLM_MODULE_OK; break; case LDAP_INVALID_CREDENTIALS: if (auth) *result = RLM_MODULE_REJECT; else { radlog(L_ERR, "rlm_ldap: LDAP login failed: check login, password settings in ldap section of radiusd.conf"); *result = RLM_MODULE_FAIL; } break; default: if (inst->is_url) radlog(L_ERR,"rlm_ldap: %s bind to %s failed %s", dn, inst->server, ldap_err2string(ldap_errno)); else radlog(L_ERR,"rlm_ldap: %s bind to %s:%d failed %s", dn, inst->server, inst->port, ldap_err2string(ldap_errno)); *result = RLM_MODULE_FAIL; } if (*result != RLM_MODULE_OK) { ldap_unbind_s(ld); ld = NULL; } return ld;}/***************************************************************************** * * Detach from the LDAP server and cleanup internal state. * *****************************************************************************/static int ldap_detach(void *instance){ ldap_instance *inst = instance; TLDAP_RADIUS *pair, *nextpair; if (inst->server) free((char *) inst->server); if (inst->login) free((char *) inst->login); if (inst->password) free((char *) inst->password); if (inst->basedn) free((char *) inst->basedn); if (inst->dictionary_mapping) free(inst->dictionary_mapping); if (inst->filter) free((char *) inst->filter); if (inst->passwd_hdr) free((char *) inst->passwd_hdr); if (inst->passwd_attr) free((char *) inst->passwd_attr); if (inst->groupname_attr) free((char *) inst->groupname_attr); if (inst->groupmemb_filt) free((char *) inst->groupmemb_filt); if (inst->groupmemb_attr) free((char *) inst->groupmemb_attr); if (inst->access_attr) free((char *) inst->access_attr); if (inst->profile_attr) free((char *) inst->profile_attr); if (inst->conns){ int i=0; for(;i<inst->num_conns;i++){ if (inst->conns[i].ld){ ldap_unbind_s(inst->conns[i].ld); } pthread_mutex_destroy(&inst->conns[i].mutex); } free(inst->conns); } pair = inst->check_item_map; while (pair != NULL) { nextpair = pair->next; free(pair->attr); free(pair->radius_attr); free(pair); pair = nextpair; } pair = inst->reply_item_map; while (pair != NULL) { nextpair = pair->next; free(pair->attr); free(pair->radius_attr); free(pair); pair = nextpair; } if (inst->atts) free(inst->atts); paircompare_unregister(PW_LDAP_GROUP, ldap_groupcmp); xlat_unregister(inst->xlat_name,ldap_xlat); free(inst->xlat_name); free(inst); return 0;}#ifdef FIELDCPYstatic void fieldcpy(char *string, char **uptr){ char *ptr; ptr = *uptr; while (*ptr == ' ' || *ptr == '\t') { ptr++; } if (*ptr == '"') { ptr++; while (*ptr != '"' && *ptr != '\0' && *ptr != '\n') { *string++ = *ptr++; } *string = '\0'; if (*ptr == '"') { ptr++; } *uptr = ptr; return; } while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' && *ptr != '=' && *ptr != ',') { *string++ = *ptr++; } *string = '\0'; *uptr = ptr; return;}#endif/***************************************************************************** * Get RADIUS attributes from LDAP object * ( according to draft-adoba-radius-05.txt * <http://www.ietf.org/internet-drafts/draft-adoba-radius-05.txt> ) * *****************************************************************************/static VALUE_PAIR *ldap_pairget(LDAP * ld, LDAPMessage * entry, TLDAP_RADIUS * item_map, VALUE_PAIR **pairs,char is_check){ char **vals; int vals_count; int vals_idx; char *ptr; TLDAP_RADIUS *element; LRAD_TOKEN token; int is_generic_attribute; char value[256]; VALUE_PAIR *pairlist = NULL; VALUE_PAIR *newpair = NULL; /* check if there is a mapping from this LDAP attribute to a RADIUS attribute */ for (element = item_map; element != NULL; element = element->next) { if ((vals = ldap_get_values(ld,entry,element->attr)) != NULL){ /* check whether this is a one-to-one-mapped ldap attribute or a generic attribute and set flag accordingly */ if (strcasecmp(element->radius_attr, GENERIC_ATTRIBUTE_ID)==0) is_generic_attribute = 1; else is_generic_attribute = 0; /* find out how many values there are for the attribute and extract all of them */ vals_count = ldap_count_values(vals); for (vals_idx = 0; vals_idx < vals_count; vals_idx++) { ptr = vals[vals_idx]; if (is_generic_attribute) { /* this is a generic attribute */ LRAD_TOKEN dummy; /* makes pairread happy */ /* not sure if using pairread here is ok ... */ if ( (newpair = pairread(&ptr, &dummy)) != NULL) { DEBUG("rlm_ldap: extracted attribute %s from generic item %s", newpair->name, vals[vals_idx]); pairadd(&pairlist, newpair); } else { radlog(L_ERR, "rlm_ldap: parsing %s failed: %s", element->attr, vals[vals_idx]); } } else { /* this is a one-to-one-mapped attribute */ token = gettoken(&ptr, value, sizeof(value) - 1); if (token < T_EQSTART || token > T_EQEND) { token = (is_check) ? T_OP_CMP_EQ : T_OP_EQ; } else { gettoken(&ptr, value, sizeof(value) - 1); } if (value[0] == 0) { DEBUG("rlm_ldap: Attribute %s has no value", element->attr); break; } DEBUG("rlm_ldap: Adding %s as %s, value %s & op=%d", element->attr, element->radius_attr, value, token); if ((newpair = pairmake(element->radius_attr, value, token)) == NULL) continue; if (! vals_idx){ pairdelete(pairs,newpair->attribute); } pairadd(&pairlist, newpair); } } ldap_value_free(vals); } } return (pairlist);}/* globally exported name */module_t rlm_ldap = { "LDAP", RLM_TYPE_THREAD_SAFE, /* type: reserved */ NULL, /* initialization */ ldap_instantiate, /* instantiation */ { ldap_authenticate, /* authentication */ ldap_authorize, /* authorization */ NULL, /* preaccounting */ NULL, /* accounting */ NULL, /* checksimul */ NULL, /* pre-proxy */ NULL, /* post-proxy */ NULL /* post-auth */ }, ldap_detach, /* detach */ NULL, /* destroy */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -