📄 rlm_ldap.c
字号:
case LDAP_SERVER_DOWN: radlog(L_ERR, "rlm_ldap: ldap_search() failed: LDAP connection lost."); conn->failed_conns++; if (search_retry == 0){ if (conn->failed_conns <= MAX_FAILED_CONNS_START){ radlog(L_INFO, "rlm_ldap: Attempting reconnect"); search_retry = 1; conn->bound = 0; ldap_msgfree(*result); goto retry; } } ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_INSUFFICIENT_ACCESS: radlog(L_ERR, "rlm_ldap: ldap_search() failed: Insufficient access. Check the identity and password configuration directives."); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_TIMEOUT: radlog(L_ERR, "rlm_ldap: ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout."); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_FILTER_ERROR: radlog(L_ERR, "rlm_ldap: ldap_search() failed: Bad search filter: %s",filter); ldap_msgfree(*result); return RLM_MODULE_FAIL; case LDAP_TIMELIMIT_EXCEEDED: case LDAP_BUSY: case LDAP_UNAVAILABLE: /* We don't need to reconnect in these cases so we don't set conn->bound */ ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", ldap_err2string(ldap_errno)); ldap_msgfree(*result); return (RLM_MODULE_FAIL); default: ldap_get_option(conn->ld, LDAP_OPT_ERROR_NUMBER, &ldap_errno); radlog(L_ERR, "rlm_ldap: ldap_search() failed: %s", ldap_err2string(ldap_errno)); conn->bound = 0; ldap_msgfree(*result); return (RLM_MODULE_FAIL); } if ((ldap_count_entries(conn->ld, *result)) != 1) { DEBUG("rlm_ldap: object not found or got ambiguous search result"); res = RLM_MODULE_NOTFOUND; ldap_msgfree(*result); } return res;}/* * Translate the LDAP queries. */static int ldap_escape_func(char *out, int outlen, const char *in){ int len = 0; while (in[0]) { /* * Only one byte left. */ if (outlen <= 1) { break; } if (strchr("*=\\,()", *in)) { static const char *hex = "0123456789abcdef"; if (outlen <= 3) break; *(out++) = '\\'; *(out++) = hex[((*in) >> 4) & 0x0f]; *(out++) = hex[(*in) & 0x0f]; outlen -= 3; continue; } /* * Else it's a nice character. */ *(out++) = *(in++); outlen--; len++; } *out = '\0'; return len;}/* * ldap_groupcmp(). Implement the Ldap-Group == "group" filter */static int ldap_groupcmp(void *instance, REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){ char filter[MAX_FILTER_STR_LEN]; char gr_filter[MAX_FILTER_STR_LEN]; int res; LDAPMessage *result = NULL; LDAPMessage *msg = NULL; char basedn[MAX_FILTER_STR_LEN]; char *attrs[] = {"dn",NULL}; char **vals; ldap_instance *inst = instance; char *group_attrs[] = {inst->groupmemb_attr,NULL}; LDAP_CONN *conn; int conn_id = -1; VALUE_PAIR *vp_user_dn; VALUE_PAIR **request_pairs; request_pairs = &req->packet->vps; DEBUG("rlm_ldap: Entering ldap_groupcmp()"); if (check->strvalue == NULL || check->length == 0){ DEBUG("rlm_ldap::ldap_groupcmp: Illegal group name"); return 1; } if (req == NULL){ DEBUG("rlm_ldap::ldap_groupcmp: NULL request"); return 1; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, req, NULL)) { DEBUG("rlm_ldap::ldap_groupcmp: unable to create basedn."); return 1; } while((vp_user_dn = pairfind(*request_pairs, PW_LDAP_USERDN)) == NULL){ char *user_dn = NULL; if (!radius_xlat(filter, sizeof(filter), inst->filter, req, ldap_escape_func)){ DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter"); return 1; } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); return 1; } if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) != RLM_MODULE_OK){ DEBUG("rlm_ldap::ldap_groupcmp: search failed"); ldap_release_conn(conn_id,inst->conns); return 1; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed"); ldap_release_conn(conn_id,inst->conns); ldap_msgfree(result); return 1; } if ((user_dn = ldap_get_dn(conn->ld, msg)) == NULL) { DEBUG("rlm_ldap:ldap_groupcmp:: ldap_get_dn() failed"); ldap_release_conn(conn_id,inst->conns); ldap_msgfree(result); return 1; } ldap_release_conn(conn_id,inst->conns); /* * Adding new attribute containing DN for LDAP object associated with * given username */ pairadd(request_pairs, pairmake("Ldap-UserDn", user_dn, T_OP_EQ)); ldap_memfree(user_dn); ldap_msgfree(result); } if(!radius_xlat(gr_filter, sizeof(gr_filter), inst->groupmemb_filt, req, NULL)){ DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter."); return 1; } if (strchr((char *)check->strvalue,',') != NULL) { /* This looks like a DN */ snprintf(filter,sizeof(filter), "%s",gr_filter); snprintf(basedn,sizeof(basedn), "%s",(char *)check->strvalue); } else snprintf(filter,sizeof(filter), "(&(%s=%s)%s)",inst->groupname_attr,(char *)check->strvalue,gr_filter); if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); return 1; } if ((res = perform_search(inst, conn, basedn, LDAP_SCOPE_SUBTREE, filter, attrs, &result)) == RLM_MODULE_OK){ DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s", (char *)check->strvalue); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return 0; } ldap_release_conn(conn_id,inst->conns); if (res != RLM_MODULE_NOTFOUND ) { DEBUG("rlm_ldap::ldap_groupcmp: Search returned error"); return 1; } if (inst->groupmemb_attr == NULL){ /* search returned NOTFOUND and searching for membership * using user object attributes is not specified in config * file */ DEBUG("rlm_ldap::ldap_groupcmp: Group %s not found or user is not a member.",(char *)check->strvalue); return 1; } snprintf(filter,sizeof(filter), "(objectclass=*)"); if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ radlog(L_ERR, "rlm_ldap: Add ldap connections are in use"); return 1; } if ((res = perform_search(inst, conn, vp_user_dn->strvalue, LDAP_SCOPE_BASE, filter, group_attrs,&result)) != RLM_MODULE_OK){ DEBUG("rlm_ldap::ldap_groupcmp: Search returned error"); ldap_release_conn(conn_id, inst->conns); return 1; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL) { DEBUG("rlm_ldap::ldap_groupcmp: ldap_first_entry() failed"); ldap_release_conn(conn_id,inst->conns); ldap_msgfree(result); return 1; } if ((vals = ldap_get_values(conn->ld, msg, inst->groupmemb_attr)) != NULL) { unsigned int i = 0; char found = 0; for (;i < ldap_count_values(vals);i++){ if (strchr(vals[i],',') != NULL){ /* This looks like a DN */ LDAPMessage *gr_result = NULL; snprintf(filter,sizeof(filter), "(%s=%s)", inst->groupname_attr, (char *)check->strvalue); if ((res = perform_search(inst, conn, vals[i], LDAP_SCOPE_BASE, filter, attrs, &gr_result)) != RLM_MODULE_OK){ if (res != RLM_MODULE_NOTFOUND){ DEBUG("rlm_ldap::ldap_groupcmp: \ Search returned error"); ldap_value_free(vals); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return 1; } } else { ldap_msgfree(gr_result); found = 1; break; } } else { if (strcmp(vals[i],(char *)check->strvalue) == 0){ found = 1; break; } } } ldap_value_free(vals); ldap_msgfree(result); if (found == 0){ DEBUG("rlm_ldap::groupcmp: Group %s not found \ or user not a member", (char *)check->strvalue); ldap_release_conn(conn_id,inst->conns); return 1; } } else { DEBUG("rlm_ldap::ldap_groupcmp: ldap_get_values() failed"); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return 1; } DEBUG("rlm_ldap::ldap_groupcmp: User found in group %s",(char *)check->strvalue); ldap_release_conn(conn_id,inst->conns); return 0;}/* * ldap_xlat() * Do an xlat on an LDAP URL */static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out, size_t freespace, RADIUS_ESCAPE_STRING func){ char url[MAX_FILTER_STR_LEN]; int res; int ret = 0; ldap_instance *inst = instance; LDAPURLDesc *ldap_url; LDAPMessage *result = NULL; LDAPMessage *msg = NULL; char **vals; int conn_id = -1; LDAP_CONN *conn; DEBUG("rlm_ldap: - ldap_xlat"); if (!radius_xlat(url, sizeof(url), fmt, request, func)) { radlog (L_ERR, "rlm_ldap: Unable to create LDAP URL.\n"); return 0; } if (!ldap_is_ldap_url(url)){ radlog (L_ERR, "rlm_ldap: String passed does not look like an LDAP URL.\n"); return 0; } if (ldap_url_parse(url,&ldap_url)){ radlog (L_ERR, "rlm_ldap: LDAP URL parse failed.\n"); return 0; } if (ldap_url->lud_attrs == NULL || ldap_url->lud_attrs[0] == NULL || \ ( ldap_url->lud_attrs[1] != NULL || ( ! strlen(ldap_url->lud_attrs[0]) || \ ! strcmp(ldap_url->lud_attrs[0],"*") ) ) ){ radlog (L_ERR, "rlm_ldap: Invalid Attribute(s) request.\n"); ldap_free_urldesc(ldap_url); return 0; } if (ldap_url->lud_host){ if (strncmp(inst->server,ldap_url->lud_host,strlen(inst->server)) != 0 || \ ldap_url->lud_port != inst->port){ DEBUG("rlm_ldap: Requested server/port is not known to this module instance."); ldap_free_urldesc(ldap_url); return 0; } } if ((conn_id = ldap_get_conn(inst->conns,&conn,inst)) == -1){ radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); ldap_free_urldesc(ldap_url); return 0; } if ((res = perform_search(inst, conn, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, ldap_url->lud_attrs, &result)) != RLM_MODULE_OK){ if (res == RLM_MODULE_NOTFOUND){ DEBUG("rlm_ldap: Search returned not found"); ldap_free_urldesc(ldap_url); ldap_release_conn(conn_id,inst->conns); return 0; } DEBUG("rlm_ldap: Search returned error"); ldap_free_urldesc(ldap_url); ldap_release_conn(conn_id,inst->conns); return 0; } if ((msg = ldap_first_entry(conn->ld, result)) == NULL){ DEBUG("rlm_ldap: ldap_first_entry() failed"); ldap_msgfree(result); ldap_free_urldesc(ldap_url); ldap_release_conn(conn_id,inst->conns); return 0; } if ((vals = ldap_get_values(conn->ld, msg, ldap_url->lud_attrs[0])) != NULL) { ret = strlen(vals[0]); if (ret > freespace){ DEBUG("rlm_ldap: Insufficient string space"); ldap_free_urldesc(ldap_url); ldap_value_free(vals); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return 0; } DEBUG("rlm_ldap: Adding attribute %s, value: %s",ldap_url->lud_attrs[0],vals[0]); strncpy(out,vals[0],ret); ldap_value_free(vals); } else ret = 0; ldap_msgfree(result); ldap_free_urldesc(ldap_url); ldap_release_conn(conn_id,inst->conns); DEBUG("rlm_ldap: - ldap_xlat end"); return ret;}/****************************************************************************** * * Function: rlm_ldap_authorize
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -