📄 rlm_ldap.c
字号:
while (in[0]) { /* * Encode unsafe characters. */ if (((len == 0) && ((in[0] == ' ') || (in[0] == '#'))) || (strchr(",+\"\\<>;*=()", *in))) { static const char hex[] = "0123456789abcdef"; /* * Only 3 or less bytes available. */ if (outlen <= 3) { break; } *(out++) = '\\'; *(out++) = hex[((*in) >> 4) & 0x0f]; *(out++) = hex[(*in) & 0x0f]; outlen -= 3; len += 3; in++; continue; } /* * Only one byte left. */ if (outlen <= 1) { break; } /* * Allowed 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, UNUSED VALUE_PAIR *request, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED 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->config_items; DEBUG("rlm_ldap: Entering ldap_groupcmp()"); if (check->vp_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, ldap_escape_func)) { 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, ldap_escape_func)) { DEBUG("rlm_ldap::ldap_groupcmp: unable to create filter."); return 1; } if (strchr((char *)check->vp_strvalue,',') != NULL) { /* This looks like a DN */ snprintf(filter,sizeof(filter), "%s",gr_filter); snprintf(basedn,sizeof(basedn), "%s",(char *)check->vp_strvalue); } else snprintf(filter,sizeof(filter), "(&(%s=%s)%s)", inst->groupname_attr, (char *)check->vp_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->vp_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->vp_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->vp_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) { 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->vp_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->vp_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->vp_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->vp_strvalue); ldap_release_conn(conn_id,inst->conns); return 0;}/* * ldap_xlat() * Do an xlat on an LDAP URL */static size_t 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; size_t 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]); strlcpy(out,vals[0],freespace); 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;}/* * For auto-header discovery. */static const FR_NAME_NUMBER header_names[] = { { "{clear}", PW_CLEARTEXT_PASSWORD }, { "{cleartext}", PW_CLEARTEXT_PASSWORD }, { "{md5}", PW_MD5_PASSWORD }, { "{smd5}", PW_SMD5_PASSWORD }, { "{crypt}", PW_CRYPT_PASSWORD }, { "{sha}", PW_SHA_PASSWORD }, { "{ssha}", PW_SSHA_PASSWORD }, { "{nt}", PW_NT_PASSWORD }, { "{ns-mta-md5}", PW_NS_MTA_MD5_PASSWORD }, { NULL, 0 }};/****************************************************************************** * * Function: rlm_ldap_authorize * * Purpose: Check if user is authorized for remote access * ******************************************************************************/static int ldap_authorize(void *instance, REQUEST * request){ LDAPMessage *result = NULL; LDAPMessage *msg = NULL; LDAPMessage *def_msg = NULL; LDAPMessage *def_attr_msg = NULL; LDAPMessage *def_result = NULL; LDAPMessage *def_attr_result = NULL; ldap_instance *inst = instance; char *user_dn = NULL; char filter[MAX_FILTER_STR_LEN]; char basedn[MAX_FILTER_STR_LEN]; VALUE_PAIR *check_tmp; VALUE_PAIR *reply_tmp; int res; VALUE_PAIR **check_pairs, **reply_pairs; char **vals; VALUE_PAIR *module_fmsg_vp; VALUE_PAIR *user_profile; char module_fmsg[MAX_STRING_LEN]; LDAP_CONN *conn; int conn_id = -1; int added_known_password = 0; DEBUG("rlm_ldap: - authorize"); if (!request->username){ DEBUG2("rlm_ldap: Attribute \"User-Name\" is required for authorization.\n"); return RLM_MODULE_NOOP; } check_pairs = &request->config_items; reply_pairs = &request->reply->vps; /* * Check for valid input, zero length names not permitted */ if (request->username->vp_strvalue == 0) { radlog(L_ERR, "rlm_ldap: zero length username not permitted\n"); return RLM_MODULE_INVALID; } DEBUG("rlm_ldap: performing user authorization for %s", request->username->vp_strvalue); if (!radius_xlat(filter, sizeof(filter), inst->filter, request, ldap_escape_func)) { radlog (L_ERR, "rlm_ldap: unable to create filter.\n"); return RLM_MODULE_INVALID; } if (!radius_xlat(basedn, sizeof(basedn), inst->basedn, request, ldap_escape_func)) { radlog (L_ERR, "rlm_ldap: unable to create basedn.\n"); return RLM_MODULE_INVALID; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -