📄 rlm_ldap.c
字号:
return i; } } return -1;}static inline void ldap_release_conn(int i, LDAP_CONN *conns){ DEBUG("rlm_ldap: ldap_release_conn: Release Id: %d",i); conns[i].locked = 0; pthread_mutex_unlock(&(conns[i].mutex));}/************************************************************************* * * Function: rlm_ldap_instantiate * * Purpose: Uses section of radiusd config file passed as parameter * to create an instance of the module. * *************************************************************************/static intldap_instantiate(CONF_SECTION * conf, void **instance){ ldap_instance *inst; int i = 0; int atts_num = 0; int reply_map_num = 0; int check_map_num = 0; int att_map[3] = {0,0,0}; TLDAP_RADIUS *pair; ATTR_FLAGS flags; char *xlat_name; inst = rad_malloc(sizeof *inst); if (!inst) { return -1; } memset(inst, 0, sizeof(*inst)); if (cf_section_parse(conf, inst, module_config) < 0) { free(inst); return -1; } if (inst->server == NULL) { radlog(L_ERR, "rlm_ldap: missing 'server' directive."); free(inst); return -1; } inst->is_url = 0; if (ldap_is_ldap_url(inst->server)){#ifdef HAVE_LDAP_INITIALIZE inst->is_url = 1; inst->port = 0;#else radlog(L_ERR, "rlm_ldap: 'server' directive is in URL form but ldap_initialize() is not available."); free(inst); return -1;#endif } inst->timeout.tv_usec = 0; inst->net_timeout.tv_usec = 0; /* workaround for servers which support LDAPS but not START TLS */ if(inst->port == LDAPS_PORT || inst->tls_mode) inst->tls_mode = LDAP_OPT_X_TLS_HARD; else inst->tls_mode = 0; inst->reply_item_map = NULL; inst->check_item_map = NULL; inst->conns = NULL; inst->failed_conns = 0; DEBUG("rlm_ldap: Registering ldap_groupcmp for Ldap-Group"); paircompare_register(PW_LDAP_GROUP, PW_USER_NAME, ldap_groupcmp, inst); xlat_name = cf_section_name2(conf); if (xlat_name != NULL){ char *group_name; DICT_ATTR *dattr; /* * Allocate room for <instance>-Ldap-Group */ group_name = malloc((strlen(xlat_name) + 1 + 11) * sizeof(char)); rad_assert(group_name != NULL); sprintf(group_name,"%s-Ldap-Group",xlat_name); DEBUG("rlm_ldap: Creating new attribute %s",group_name); dict_addattr(group_name, 0, PW_TYPE_STRING, -1, flags); dattr = dict_attrbyname(group_name); if (dattr == NULL){ radlog(L_ERR, "rlm_ldap: Failed to create attribute %s",group_name); free(inst); return -1; } DEBUG("rlm_ldap: Registering ldap_groupcmp for %s",group_name); paircompare_register(dattr->attr, PW_USER_NAME, ldap_groupcmp, inst); } else { xlat_name = cf_section_name1(conf); rad_assert(xlat_name != NULL); /* or all hell breaks loose */ } inst->xlat_name = strdup(xlat_name); DEBUG("rlm_ldap: Registering ldap_xlat with xlat_name %s",xlat_name); xlat_register(xlat_name,ldap_xlat,inst);#ifdef NOVELL /* * (LDAP_Instance, V1) attribute-value pair in the config items list means * that the 'authorize' method of the instance 'V1' of the LDAP module has * processed this request. */ dict_addattr("LDAP-Instance", 0, PW_TYPE_STRING, -1, flags); /* * ('eDir-APC', '1') in config items list => Do not perform eDirectory account * policy check (APC) * ('eDir-APC', '2') in config items list => Perform eDirectory APC * ('eDir-APC', '3') in config items list => eDirectory APC has been completed */ dict_addattr("eDir-APC", 0, PW_TYPE_INTEGER, -1, flags);#endif if (inst->num_conns <= 0){ radlog(L_ERR, "rlm_ldap: Invalid ldap connections number passed."); free(inst); return -1; } inst->conns = (LDAP_CONN *)malloc(sizeof(LDAP_CONN)*inst->num_conns); if (inst->conns == NULL){ radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting."); free(inst); return -1; } for(;i<inst->num_conns;i++){ inst->conns[i].bound = 0; inst->conns[i].locked = 0; inst->conns[i].failed_conns = 0; inst->conns[i].ld = NULL; pthread_mutex_init(&inst->conns[i].mutex, NULL); }#ifdef NOVELL /* * 'inst->apc_conns' is a separate connection pool to be used for performing * eDirectory account policy check in the 'postauth' method. This avoids * changing the (RADIUS server) credentials associated with the 'inst->conns' * connection pool. */ inst->apc_conns = (LDAP_CONN *)malloc(sizeof(LDAP_CONN)*inst->num_conns); if (inst->apc_conns == NULL){ radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting."); free(inst); return -1; } for(i = 0; i < inst->num_conns; i++){ inst->apc_conns[i].bound = 0; inst->apc_conns[i].locked = 0; inst->apc_conns[i].failed_conns = 0; inst->apc_conns[i].ld = NULL; pthread_mutex_init(&inst->apc_conns[i].mutex, NULL); }#endif if (read_mappings(inst) != 0) { radlog(L_ERR, "rlm_ldap: Reading dictionary mappings from file %s failed", inst->dictionary_mapping); free(inst); return -1; } if (inst->check_item_map == NULL && inst->reply_item_map == NULL){ radlog(L_ERR, "rlm_ldap: dictionary mappings file %s did not contain any mappings", inst->dictionary_mapping); free(inst); return -1; } pair = inst->check_item_map; while(pair != NULL){ atts_num++; pair = pair->next; } check_map_num = (atts_num - 1); pair = inst->reply_item_map; while(pair != NULL){ atts_num++; pair = pair->next; } reply_map_num = (atts_num - 1); if (inst->profile_attr) atts_num++; if (inst->passwd_attr) atts_num++; if (inst->access_attr) atts_num++; inst->atts = (char **)malloc(sizeof(char *)*(atts_num + 1)); if (inst->atts == NULL){ radlog(L_ERR, "rlm_ldap: Could not allocate memory. Aborting."); free(inst); return -1; } pair = inst->check_item_map; if (pair == NULL) pair = inst->reply_item_map; for(i=0;i<atts_num;i++){ if (i <= check_map_num ){ inst->atts[i] = pair->attr; if (i == check_map_num) pair = inst->reply_item_map; else pair = pair->next; } else if (i <= reply_map_num){ inst->atts[i] = pair->attr; pair = pair->next; } else{ if (inst->profile_attr && !att_map[0]){ inst->atts[i] = inst->profile_attr; att_map[0] = 1; } else if (inst->passwd_attr && !att_map[1]){ inst->atts[i] = inst->passwd_attr; att_map[1] = 1; } else if (inst->access_attr && !att_map[2]){ inst->atts[i] = inst->access_attr; att_map[2] = 1; } } } inst->atts[atts_num] = NULL; DEBUG("conns: %p",inst->conns); *instance = inst; return 0;}/* * read_mappings(...) reads a ldap<->radius mappings file to inst->reply_item_map and inst->check_item_map */#define MAX_LINE_LEN 160#define GENERIC_ATTRIBUTE_ID "$GENERIC$"static intread_mappings(ldap_instance* inst){ FILE* mapfile; char *filename; /* all buffers are of MAX_LINE_LEN so we can use sscanf without being afraid of buffer overflows */ char buf[MAX_LINE_LEN], itemType[MAX_LINE_LEN], radiusAttribute[MAX_LINE_LEN], ldapAttribute[MAX_LINE_LEN]; int linenumber; /* open the mappings file for reading */ filename = inst->dictionary_mapping; DEBUG("rlm_ldap: reading ldap<->radius mappings from file %s", filename); mapfile = fopen(filename, "r"); if (mapfile == NULL) { radlog(L_ERR, "rlm_ldap: Opening file %s failed", filename); return -1; /* error */ } /* read file line by line. Note that if line length exceed MAX_LINE_LEN, line numbers will be mixed up */ linenumber = 0; while (fgets(buf, sizeof buf, mapfile)!=NULL) { char* ptr; int token_count; TLDAP_RADIUS* pair; linenumber++; /* strip comments */ ptr = strchr(buf, '#'); if (ptr) *ptr = 0; /* empty line */ if (buf[0] == 0) continue; /* extract tokens from the string */ token_count = sscanf(buf, "%s %s %s", itemType, radiusAttribute, ldapAttribute); if (token_count <= 0) /* no tokens */ continue; if (token_count != 3) { radlog(L_ERR, "rlm_ldap: Skipping %s line %i: %s", filename, linenumber, buf); radlog(L_ERR, "rlm_ldap: Expected 3 tokens " "(Item type, RADIUS Attribute and LDAP Attribute) but found only %i", token_count); continue; } /* create new TLDAP_RADIUS list node */ pair = rad_malloc(sizeof(TLDAP_RADIUS)); pair->attr = strdup(ldapAttribute); pair->radius_attr = strdup(radiusAttribute); if ( (pair->attr == NULL) || (pair->radius_attr == NULL) ) { radlog(L_ERR, "rlm_ldap: Out of memory"); if (pair->attr) free(pair->attr); if (pair->radius_attr) free(pair->radius_attr); free(pair); fclose(mapfile); return -1; } /* push node to correct list */ if (strcasecmp(itemType, "checkItem") == 0) { pair->next = inst->check_item_map; inst->check_item_map = pair; } else if (strcasecmp(itemType, "replyItem") == 0) { pair->next = inst->reply_item_map; inst->reply_item_map = pair; } else { radlog(L_ERR, "rlm_ldap: file %s: skipping line %i: unknown itemType %s", filename, linenumber, itemType); free(pair->attr); free(pair->radius_attr); free(pair); continue; } DEBUG("rlm_ldap: LDAP %s mapped to RADIUS %s", pair->attr, pair->radius_attr); } fclose(mapfile); return 0; /* success */}static intperform_search(void *instance, LDAP_CONN *conn, char *search_basedn, int scope, char *filter, char **attrs, LDAPMessage ** result){ int res = RLM_MODULE_OK; int ldap_errno = 0; ldap_instance *inst = instance; int search_retry = 0; *result = NULL; if (!conn){ radlog(L_ERR, "rlm_ldap: NULL connection handle passed"); return RLM_MODULE_FAIL; } if (conn->failed_conns > MAX_FAILED_CONNS_START){ conn->failed_conns++; if (conn->failed_conns >= MAX_FAILED_CONNS_END){ conn->failed_conns = MAX_FAILED_CONNS_RESTART; conn->bound = 0; } }retry: 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, inst->login, inst->password, 0, &res, NULL)) == NULL) { radlog(L_ERR, "rlm_ldap: (re)connection attempt failed"); if (search_retry == 0) conn->failed_conns++; return (RLM_MODULE_FAIL); } conn->bound = 1; conn->failed_conns = 0; } DEBUG2("rlm_ldap: performing search in %s, with filter %s", search_basedn ? search_basedn : "(null)" , filter); switch (ldap_search_st(conn->ld, search_basedn, scope, filter, attrs, 0, &(inst->timeout), result)) { case LDAP_SUCCESS: case LDAP_NO_SUCH_OBJECT: break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -