24RCSID(
"$Id: c2cc907ccdd203f13be0bc9e9122dc0345974839 $")
26#include <freeradius-devel/curl/base.h>
27#include <freeradius-devel/curl/xlat.h>
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/cf_parse.h>
31#include <freeradius-devel/server/global_lib.h>
32#include <freeradius-devel/server/tmpl.h>
33#include <freeradius-devel/server/log.h>
34#include <freeradius-devel/util/atexit.h>
35#include <freeradius-devel/util/debug.h>
36#include <freeradius-devel/util/uri.h>
37#include <freeradius-devel/unlang/call_env.h>
38#include <freeradius-devel/unlang/xlat_func.h>
40#define FTP_BODY_ALLOC_CHUNK 1024
130 if (!escaped)
return -1;
135 if (strlen(escaped) == vb->vb_length) {
180 ftp_slab_release(handle);
193 RDEBUG2(
"Forcefully cancelling pending FTP request");
196 if (ret != CURLM_OK) {
197 RERROR(
"Failed removing curl handle from multi-handle: %s (%i)", curl_multi_strerror(ret), ret);
202 ftp_slab_release(randle);
211 char const *start =
in, *p = start, *end = p + (size * nmemb);
215 if (start == end)
return 0;
218 REDEBUG(
"Incoming data (%zu bytes) exceeds max_body_in (%zu bytes). "
226 if (needed > ctx->
alloc) {
232 memcpy(out_p, p, (end - p));
235 ctx->
used += (end - p);
239 return (end - start);
259 fr_value_box_list_t *
in)
293 randle = rctx->
handle = ftp_slab_reserve(t->
slab);
299 RDEBUG2(
"Sending FTP GET to \"%pV\"", uri_vb);
306#if CURL_AT_LEAST_VERSION(7,85,0)
319 ftp_slab_release(randle);
340 CURL *candle = randle->
candle;
345 curl_easy_reset(candle);
355 ret = curl_easy_setopt(candle, CURLOPT_PRIVATE, (
void *)0xdeadc341);
357 ERROR(
"Failed to set private data on curl easy handle %p: %s",
358 candle, curl_easy_strerror(ret));
376 curl_easy_cleanup(randle->
candle);
385 randle->
candle = curl_easy_init();
394 randle->
uctx = curl_ctx;
420 if (!(t->
slab = ftp_slab_list_alloc(t, mctx->
el, &
inst->conn_config.reuse,
422 ERROR(
"Connection handle pool instantiation failed");
427 if (!mhandle)
return -1;
468 inst->conn_config.reuse.num_children = 1;
#define L(_str)
Helper for initialising arrays of string literals.
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
fr_curl_handle_t * fr_curl_io_init(TALLOC_CTX *ctx, fr_event_list_t *el, bool multiplex)
#define FR_CURL_REQUEST_SET_OPTION(_x, _y)
uint64_t transfers
How many transfers are current in progress.
CURLM * mandle
The multi handle.
request_t * request
Current request.
void * uctx
Private data for the module using the API.
int fr_curl_io_request_enqueue(fr_curl_handle_t *mhandle, request_t *request, fr_curl_io_request_t *creq)
Sends a request using libcurl.
CURL * candle
Request specific handle.
Uctx data for timer and I/O functions.
Structure representing an individual request being passed to curl for processing.
#define CURL_URI_SAFE_FOR
safe for value suitable for all users of the curl library
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define GLOBAL_LIB_TERMINATOR
Structure to define how to initialise libraries with global configuration.
static xlat_action_t ftp_get_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Simple xlat to read data from an FTP URI.
global_lib_autoinst_t fr_curl_autoinst
CURL * fr_curl_tmp_handle(void)
Return a thread local curl easy handle.
conf_parser_t fr_curl_conn_config[]
#define RPEDEBUG(fmt,...)
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
@ FR_TYPE_OCTETS
Raw octets.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
static int ftp_uri_part_escape(fr_value_box_t *vb, void *uctx)
static int _ftp_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
Cleans up after a FTP request.
size_t used
Space used in buffer.
static fr_uri_part_t const ftp_uri_parts[]
fr_curl_handle_t * mhandle
Thread specific multi handle.
static size_t ftp_response_body(void *in, size_t size, size_t nmemb, void *userdata)
static void ftp_io_xlat_signal(xlat_ctx_t const *xctx, request_t *request, UNUSED fr_signal_t action)
bool binary
Do we expect binary data - and so output octets.
request_t * request
Current request.
fr_curl_io_request_t * handle
curl easy handle servicing our request.
static int ftp_conn_alloc(fr_curl_io_request_t *randle, void *uctx)
write_state_t state
Decoder state.
static int mod_bootstrap(module_inst_ctx_t const *mctx)
size_t max_resp_size
Maximum size of incoming data.
size_t alloc
Space allocated for buffer.
static xlat_arg_parser_t const ftp_get_xlat_args[]
global_lib_autoinst_t const *const rlm_ftp_lib[]
char * buffer
Raw incoming FTP data.
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Create a thread specific multihandle.
fr_curl_conn_config_t conn_config
Configuration of slab allocated connection handles.
rlm_ftp_t const * instance
This instance of rlm_ftp.
rlm_ftp_t const * inst
Instance of rlm_ftp.
static const conf_parser_t module_config[]
rlm_ftp_response_t response
Response context data.
static int _mod_conn_free(fr_curl_io_request_t *randle)
#define FTP_BODY_ALLOC_CHUNK
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Cleanup all outstanding requests associated with this thread.
static int mod_instantiate(module_inst_ctx_t const *mctx)
ftp_slab_list_t * slab
Slab list for connection handles.
static xlat_action_t ftp_get_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, UNUSED request_t *request, UNUSED fr_value_box_list_t *in)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
#define FR_SLAB_FUNCS(_name, _type)
Define type specific wrapper functions for slabs and slab elements.
#define FR_SLAB_TYPES(_name, _type)
Define type specific wrapper structs for slabs and slab elements.
eap_aka_sim_process_conf_t * inst
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
uint8_t required
Argument must be present, and non-empty.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
int fr_uri_escape_list(fr_value_box_list_t *uri, fr_uri_part_t const *uri_parts, void *uctx)
Parse a list of value boxes representing a URI.
#define XLAT_URI_PART_TERMINATOR
char const * name
Name of this part of the URI.
Definition for a single part of a URI.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
void * rctx
Resume context.
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.