📄 rlm_ldap.c
字号:
if (inst->do_xlat){ pairxlatmove(request, check_pairs, &check_tmp); pairfree(&check_tmp); } else pairadd(check_pairs,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) { if (inst->do_xlat){ pairxlatmove(request, reply_pairs, &reply_tmp); pairfree(&reply_tmp); } else pairadd(reply_pairs,reply_tmp); } if (inst->do_comp && paircmp(request,request->packet->vps,*check_pairs,reply_pairs) != 0){#ifdef NOVELL /* Don't perform eDirectory APC if RADIUS authorize fails */ int apc_attr; VALUE_PAIR *vp_apc; DICT_ATTR *dattr; dattr = dict_attrbyname("eDir-APC"); apc_attr = dattr->attr; vp_apc = pairfind(request->config_items, apc_attr); if(vp_apc) vp_apc->strvalue[0] = '1';#endif 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_AUTH_TYPE) == NULL) && request->password && (request->password->attribute == PW_USER_PASSWORD)) 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 intldap_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;#ifdef NOVELL char *err = NULL;#endif 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) { snprintf(module_fmsg,sizeof(module_fmsg),"rlm_ldap: empty password supplied"); module_fmsg_vp = pairmake("Module-Failure-Message", module_fmsg, T_OP_EQ); pairadd(&request->packet->vps, module_fmsg_vp); 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);#ifndef NOVELL ld_user = ldap_connect(instance, user_dn, request->password->strvalue, 1, &res, NULL);#else ld_user = ldap_connect(instance, user_dn, request->password->strvalue, 1, &res, &err); if(err != NULL){ /* 'err' contains the LDAP connection error description */ DEBUG("rlm_ldap: %s", err); pairadd(&request->reply->vps, pairmake("Reply-Message", err, T_OP_EQ)); ldap_memfree((void *)err); } /* Don't perform eDirectory APC again after attempting to bind here. */ { int apc_attr; DICT_ATTR *dattr; VALUE_PAIR *vp_apc; dattr = dict_attrbyname("eDir-APC"); apc_attr = dattr->attr; vp_apc = pairfind(request->config_items, apc_attr); if(vp_apc && vp_apc->strvalue[0] == '2') vp_apc->strvalue[0] = '3'; }#endif 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;}#ifdef NOVELL/***************************************************************************** * * Function: rlm_ldap_postauth * * Purpose: Perform eDirectory account policy check and failed-login reporting * to eDirectory. * *****************************************************************************/static intldap_postauth(void *instance, REQUEST * request){ int res = RLM_MODULE_FAIL; int inst_attr, apc_attr; char password[UNIVERSAL_PASS_LEN]; ldap_instance *inst = instance; LDAP_CONN *conn; VALUE_PAIR *vp_inst, *vp_apc; DICT_ATTR *dattr; dattr = dict_attrbyname("LDAP-Instance"); inst_attr = dattr->attr; dattr = dict_attrbyname("eDir-APC"); apc_attr = dattr->attr; vp_inst = pairfind(request->config_items, inst_attr); /* * Check if the password in the config items list is the user's UP which has * been read in the authorize method of this instance of the LDAP module. */ if((vp_inst == NULL) || strcmp(vp_inst->strvalue, inst->xlat_name)) return RLM_MODULE_NOOP; vp_apc = pairfind(request->config_items, apc_attr); switch(vp_apc->strvalue[0]){ case '1': /* Account policy check not enabled */ case '3': /* Account policy check has been completed */ res = RLM_MODULE_NOOP; break; case '2': { int err, conn_id = -1; char *error_msg = NULL; VALUE_PAIR *vp_fdn, *vp_pwd; DICT_ATTR *da; if(request->reply->code == PW_AUTHENTICATION_REJECT){ /* Bind to eDirectory as the RADIUS user with a wrong password. */ vp_pwd = pairfind(request->config_items, PW_PASSWORD); strcpy(password, vp_pwd->strvalue); if(strlen(password) > 0){ if(password[0] != 'a'){ password[0] = 'a'; }else{ password[0] = 'b'; } }else{ strcpy(password, "dummy_password"); } res = RLM_MODULE_REJECT; }else{ /* Bind to eDirectory as the RADIUS user using the user's UP */ vp_pwd = pairfind(request->config_items, PW_PASSWORD); if(vp_pwd == NULL){ DEBUG("rlm_ldap: User's Universal Password not in config items list."); return RLM_MODULE_FAIL; } strcpy(password, vp_pwd->strvalue); } if ((da = dict_attrbyname("Ldap-UserDn")) == NULL) { DEBUG("rlm_ldap: Attribute for user FDN not found in dictionary. Unable to proceed"); return RLM_MODULE_FAIL; } vp_fdn = pairfind(request->packet->vps, da->attr); if(vp_fdn == NULL){ DEBUG("rlm_ldap: User's FQDN not in config items list."); return RLM_MODULE_FAIL; } if ((conn_id = ldap_get_conn(inst->apc_conns, &conn, inst)) == -1){ radlog(L_ERR, "rlm_ldap: All ldap connections are in use"); return RLM_MODULE_FAIL; } /* * If there is an existing LDAP connection to the directory, bind over * it. Otherwise, establish a new connection. */postauth_reconnect: if (!conn->bound || conn->ld == NULL) { DEBUG2("rlm_ldap: attempting LDAP reconnection"); if (conn->ld){ DEBUG2("rlm_ldap: closing existing LDAP connection"); ldap_unbind_s(conn->ld); } if ((conn->ld = ldap_connect(instance, (char *)vp_fdn->strvalue, password, 0, &res, &error_msg)) == NULL) { radlog(L_ERR, "rlm_ldap: eDirectory account policy check failed."); if(error_msg != NULL){ DEBUG("rlm_ldap: %s", error_msg); pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ)); ldap_memfree((void *)error_msg); } vp_apc->strvalue[0] = '3'; ldap_release_conn(conn_id, inst->apc_conns); return RLM_MODULE_REJECT; } conn->bound = 1; }else if((err = ldap_simple_bind_s(conn->ld, (char *)vp_fdn->strvalue, password)) != LDAP_SUCCESS){ if(err == LDAP_SERVER_DOWN){ conn->bound = 0; goto postauth_reconnect; } DEBUG("rlm_ldap: eDirectory account policy check failed."); ldap_get_option(conn->ld, LDAP_OPT_ERROR_STRING, &error_msg); if(error_msg != NULL){ DEBUG("rlm_ldap: %s", error_msg); pairadd(&request->reply->vps, pairmake("Reply-Message", error_msg, T_OP_EQ)); ldap_memfree((void *)error_msg); } vp_apc->strvalue[0] = '3'; ldap_release_conn(conn_id, inst->apc_conns); return RLM_MODULE_REJECT; } vp_apc->strvalue[0] = '3'; ldap_release_conn(conn_id, inst->apc_conns); return RLM_MODULE_OK; } } return res;}#endifstatic LDAP *ldap_connect(void *instance, const char *dn, const char *password, int auth, int *result, char **err){ 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_INITIA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -