📄 rlm_ldap.c
字号:
* Do an xlat on an LDAP URL */static int ldap_xlat(void *instance, REQUEST *request, char *fmt, char *out, int 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 * * 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; DEBUG("rlm_ldap: - authorize"); if (!request->username){ radlog(L_AUTH, "rlm_ldap: Attribute \"User-Name\" is required for authentication.\n"); return RLM_MODULE_INVALID; } check_pairs = &request->config_items; reply_pairs = &request->reply->vps; /* * Check for valid input, zero length names not permitted */ if (request->username->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->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, 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, inst->atts, &result)) != RLM_MODULE_OK) { DEBUG("rlm_ldap: search failed"); 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) { DEBUG("rlm_ldap: ldap_first_entry() failed"); 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; } /* * Adding new attribute containing DN for LDAP object associated with * given username */ pairadd(&request->packet->vps, pairmake("Ldap-UserDn", user_dn, T_OP_EQ)); ldap_memfree(user_dn); /* Remote access is controled by attribute of the user object */ if (inst->access_attr) { if ((vals = ldap_get_values(conn->ld, msg, inst->access_attr)) != NULL) { if (inst->default_allow){ DEBUG("rlm_ldap: checking if remote access for %s is allowed by %s", request->username->strvalue, inst->access_attr); if (!strncmp(vals[0], "FALSE", 5)) { DEBUG("rlm_ldap: dialup access disabled"); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_value_free(vals); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_USERLOCK; } ldap_value_free(vals); } else{ DEBUG("rlm_ldap: %s attribute exists - access denied by default", inst->access_attr); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_value_free(vals); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_USERLOCK; } } else { if (inst->default_allow){ DEBUG("rlm_ldap: no %s attribute - access denied by default", inst->access_attr); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Access Attribute denies access"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_USERLOCK; } } } /* * Check for the default profile entry. If it exists then add the * attributes it contains in the check and reply pairs */ user_profile = pairfind(request->config_items, PW_USER_PROFILE); if (inst->default_profile || user_profile){ char *profile = inst->default_profile; strNcpy(filter,"(objectclass=radiusprofile)",sizeof(filter)); if (user_profile) profile = user_profile->strvalue; if (profile && strlen(profile)){ if ((res = perform_search(instance, conn, profile, LDAP_SCOPE_BASE, filter, inst->atts, &def_result)) == RLM_MODULE_OK){ if ((def_msg = ldap_first_entry(conn->ld,def_result))){ if ((check_tmp = ldap_pairget(conn->ld,def_msg,inst->check_item_map,check_pairs,1))) { /*pairadd(check_pairs,check_tmp);*/ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); } if ((reply_tmp = ldap_pairget(conn->ld,def_msg,inst->reply_item_map,reply_pairs,0))) { /*pairadd(reply_pairs,reply_tmp);*/ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); } } ldap_msgfree(def_result); } else DEBUG("rlm_ldap: default_profile/user-profile search failed"); } } /* * Check for the profile attribute. If it exists, we assume that it * contains the DN of an entry containg a profile for the user. That * way we can have different general profiles for various user groups * (students,faculty,staff etc) */ if (inst->profile_attr){ if ((vals = ldap_get_values(conn->ld, msg, inst->profile_attr)) != NULL) { unsigned int i=0; strNcpy(filter,"(objectclass=radiusprofile)",sizeof(filter)); while(vals[i] != NULL && strlen(vals[i])){ if ((res = perform_search(instance, conn, vals[i], LDAP_SCOPE_BASE, filter, inst->atts, &def_attr_result)) == RLM_MODULE_OK){ if ((def_attr_msg = ldap_first_entry(conn->ld,def_attr_result))){ if ((check_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->check_item_map,check_pairs,1))) { /*pairadd(check_pairs,check_tmp);*/ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); } if ((reply_tmp = ldap_pairget(conn->ld,def_attr_msg,inst->reply_item_map,reply_pairs,0))) { /*pairadd(reply_pairs,reply_tmp);*/ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); } } ldap_msgfree(def_attr_result); } else DEBUG("rlm_ldap: profile_attribute search failed"); i++; } ldap_value_free(vals); } } if (inst->passwd_attr && strlen(inst->passwd_attr)){ VALUE_PAIR *passwd_item; if ((passwd_item = pairfind(request->config_items, PW_PASSWORD)) == NULL){ char **passwd_vals; char *passwd_val = NULL; int passwd_len; if ((passwd_vals = ldap_get_values(conn->ld,msg,inst->passwd_attr)) != NULL){ unsigned int i=0; while(passwd_vals[i] != NULL){ if (strlen(passwd_vals[i])){ passwd_val = passwd_vals[i]; if (inst->passwd_hdr && strlen(inst->passwd_hdr)){ passwd_val = strstr(passwd_val,inst->passwd_hdr); if (passwd_val != NULL) passwd_val += strlen(inst->passwd_hdr); else DEBUG("rlm_ldap: Password header not found in password %s for user %s", passwd_vals[0],request->username->strvalue); } if (passwd_val){ if ((passwd_item = paircreate(PW_PASSWORD,PW_TYPE_STRING)) == NULL){ radlog(L_ERR|L_CONS, "no memory"); ldap_value_free(passwd_vals); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_FAIL; } passwd_len = strlen(passwd_val); strncpy(passwd_item->strvalue,passwd_val,MAX_STRING_LEN - 1); passwd_item->length = (passwd_len > (MAX_STRING_LEN - 1)) ? (MAX_STRING_LEN - 1) : passwd_len; pairadd(&request->config_items,passwd_item); DEBUG("rlm_ldap: Added password %s in check items",passwd_item->strvalue); } } i++; } ldap_value_free(passwd_vals); } } } DEBUG("rlm_ldap: looking for check items in directory..."); if ((check_tmp = ldap_pairget(conn->ld, msg, inst->check_item_map,check_pairs,1)) != NULL) { /*pairadd(check_pairs,check_tmp);*/ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); } DEBUG("rlm_ldap: looking for reply items in directory..."); if ((reply_tmp = ldap_pairget(conn->ld, msg, inst->reply_item_map,reply_pairs,0)) != NULL) { /*pairadd(reply_pairs,reply_tmp);*/ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); } if (inst->do_comp && paircmp(request,request->packet->vps,*check_pairs,reply_pairs) != 0){ DEBUG("rlm_ldap: Pairs do not match. Rejecting user."); snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: Pairs do not match"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_REJECT; } /* * Module should default to LDAP authentication if no Auth-Type * specified */ if (pairfind(*check_pairs, PW_AUTHTYPE) == NULL) pairadd(check_pairs, pairmake("Auth-Type", "LDAP", T_OP_EQ)); DEBUG("rlm_ldap: user %s authorized to use remote access", request->username->strvalue); ldap_msgfree(result); ldap_release_conn(conn_id,inst->conns); return RLM_MODULE_OK;}/***************************************************************************** * * Function: rlm_ldap_authenticate * * Purpose: Check the user's password against ldap database * *****************************************************************************/static int ldap_authenticate(void *instance, REQUEST * request){ LDAP *ld_user; LDAPMessage *result, *msg; ldap_instance *inst = instance; char *user_dn, *attrs[] = {"uid", NULL}; char filter[MAX_FILTER_STR_LEN]; char basedn[MAX_FILTER_STR_LEN]; int res; VALUE_PAIR *vp_user_dn; VALUE_PAIR *module_fmsg_vp; char module_fmsg[MAX_STRING_LEN]; LDAP_CONN *conn; int conn_id = -1; DEBUG("rlm_ldap: - authenticate"); /* * Ensure that we're being passed a plain-text password, and not * anything else. */ if (!request->username) { radlog(L_AUTH, "rlm_ldap: Attribute \"User-Name\" is required for authentication.\n"); return RLM_MODULE_INVALID; } if (!request->password){ radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication."); return RLM_MODULE_INVALID; } if(request->password->attribute != PW_PASSWORD) { radlog(L_AUTH, "rlm_ldap: Attribute \"User-Password\" is required for authentication. Cannot use \"%s\".", request->password->name); return RLM_MODULE_INVALID; } if (request->password->length == 0) { radlog(L_ERR, "rlm_ldap: empty password supplied");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -