/** Print one attribute value to a string * * @param ctx to allocate string in. * @param vp to print. * @param[in] quote the quotation character * @return a talloced buffer with the attribute operator and value. */ char *vp_aprints_value(TALLOC_CTX *ctx, VALUE_PAIR const *vp, char quote) { VERIFY_VP(vp); if (vp->type == VT_XLAT) { return fr_aprints(ctx, vp->value.xlat, talloc_array_length(vp->value.xlat) - 1, quote); } return value_data_aprints(ctx, vp->da->type, vp->da, &vp->data, vp->vp_length, quote); }
/* * Convert field X to a VP. */ static int csv_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx) { char const *str = uctx; VALUE_PAIR *head = NULL, *vp; vp_cursor_t cursor; DICT_ATTR const *da; rad_assert(ctx != NULL); fr_cursor_init(&cursor, &head); /* * FIXME: allow multiple entries. */ if (map->lhs->type == TMPL_TYPE_ATTR) { da = map->lhs->tmpl_da; } else { char *attr; if (tmpl_aexpand(ctx, &attr, request, map->lhs, NULL, NULL) <= 0) { RWDEBUG("Failed expanding string"); return -1; } da = dict_attrbyname(attr); if (!da) { RWDEBUG("No such attribute '%s'", attr); return -1; } talloc_free(attr); } vp = pairalloc(ctx, da); rad_assert(vp); if (pairparsevalue(vp, str, talloc_array_length(str) - 1) < 0) { char *escaped; escaped = fr_aprints(vp, str, talloc_array_length(str) - 1, '\''); RWDEBUG("Failed parsing value \"%s\" for attribute %s: %s", escaped, map->lhs->tmpl_da->name, fr_strerror()); talloc_free(vp); /* also frees escaped */ return -1; } vp->op = map->op; fr_cursor_merge(&cursor, vp); *out = head; return 0; }
ldap_rcode_t rlm_ldap_sasl_interactive(rlm_ldap_t const *inst, REQUEST *request, ldap_handle_t *conn, char const *identity, char const *password, ldap_sasl *sasl, char const **error, char **extra) { ldap_rcode_t status; int ret = 0; int msgid; char const *mech; LDAPMessage *result = NULL; rlm_ldap_sasl_ctx_t sasl_ctx; /* SASL defaults */ memset(&sasl_ctx, 0, sizeof(sasl_ctx)); sasl_ctx.inst = inst; sasl_ctx.request = request; sasl_ctx.identity = identity; sasl_ctx.password = password; ROPTIONAL(RDEBUG2, DEBUG2, "Starting SASL mech(s): %s", sasl->mech); do { ret = ldap_sasl_interactive_bind(conn->handle, NULL, sasl->mech, NULL, NULL, LDAP_SASL_AUTOMATIC, _sasl_interact, &sasl_ctx, result, &mech, &msgid); ldap_msgfree(result); /* We always need to free the old message */ if (ret >= 0) ROPTIONAL(RDEBUG3, DEBUG3, "Continuing SASL mech %s...", mech); status = rlm_ldap_result(inst, conn, msgid, identity, &result, error, extra); /* * Write the servers response to the debug log */ if (((request && RDEBUG_ENABLED3) || DEBUG_ENABLED3) && result) { struct berval *srv_cred; if (ldap_parse_sasl_bind_result(conn->handle, result, &srv_cred, 0) == 0) { char *escaped; escaped = fr_aprints(request, srv_cred->bv_val, srv_cred->bv_len, '\0'); ROPTIONAL(RDEBUG3, DEBUG3, "SASL response : %s", escaped); talloc_free(escaped); ldap_memfree(srv_cred); } } } while (status == LDAP_PROC_CONTINUE); ldap_msgfree(result); return status; }
/** Callback for map_to_request * * Performs exactly the same job as map_to_vp, but pulls attribute values from LDAP entries * * @see map_to_vp */ int rlm_ldap_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx) { rlm_ldap_result_t *self = uctx; VALUE_PAIR *head = NULL, *vp; vp_cursor_t cursor; int i; fr_cursor_init(&cursor, &head); switch (map->lhs->type) { /* * This is a mapping in the form of: * <list>: += <ldap attr> * * Where <ldap attr> is: * <list>:<attr> <op> <value> * * It is to allow for legacy installations which stored * RADIUS control and reply attributes in separate LDAP * attributes. */ case TMPL_TYPE_LIST: for (i = 0; i < self->count; i++) { vp_map_t *attr = NULL; RDEBUG3("Parsing valuepair string \"%s\"", self->values[i]->bv_val); if (map_afrom_attr_str(ctx, &attr, self->values[i]->bv_val, map->lhs->tmpl_request, map->lhs->tmpl_list, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) { RWDEBUG("Failed parsing \"%s\" as valuepair (%s), skipping...", fr_strerror(), self->values[i]->bv_val); continue; } if (attr->lhs->tmpl_request != map->lhs->tmpl_request) { RWDEBUG("valuepair \"%s\" has conflicting request qualifier (%s vs %s), skipping...", self->values[i]->bv_val, fr_int2str(request_refs, attr->lhs->tmpl_request, "<INVALID>"), fr_int2str(request_refs, map->lhs->tmpl_request, "<INVALID>")); next_pair: talloc_free(attr); continue; } if ((attr->lhs->tmpl_list != map->lhs->tmpl_list)) { RWDEBUG("valuepair \"%s\" has conflicting list qualifier (%s vs %s), skipping...", self->values[i]->bv_val, fr_int2str(pair_lists, attr->lhs->tmpl_list, "<INVALID>"), fr_int2str(pair_lists, map->lhs->tmpl_list, "<INVALID>")); goto next_pair; } if (map_to_vp(request, &vp, request, attr, NULL) < 0) { RWDEBUG("Failed creating attribute for valuepair \"%s\", skipping...", self->values[i]->bv_val); goto next_pair; } fr_cursor_merge(&cursor, vp); talloc_free(attr); /* * Only process the first value, unless the operator is += */ if (map->op != T_OP_ADD) break; } break; /* * Iterate over all the retrieved values, * don't try and be clever about changing operators * just use whatever was set in the attribute map. */ case TMPL_TYPE_ATTR: for (i = 0; i < self->count; i++) { if (!self->values[i]->bv_len) continue; vp = pairalloc(ctx, map->lhs->tmpl_da); rad_assert(vp); if (pairparsevalue(vp, self->values[i]->bv_val, self->values[i]->bv_len) < 0) { char *escaped; escaped = fr_aprints(vp, self->values[i]->bv_val, self->values[i]->bv_len, '"'); RWDEBUG("Failed parsing value \"%s\" for attribute %s: %s", escaped, map->lhs->tmpl_da->name, fr_strerror()); talloc_free(vp); /* also frees escaped */ continue; } vp->op = map->op; fr_cursor_insert(&cursor, vp); /* * Only process the first value, unless the operator is += */ if (map->op != T_OP_ADD) break; } break; default: rad_assert(0); } *out = head; return 0; }