|
101 | 101 |
|
102 | 102 | module AP_MODULE_DECLARE_DATA crowdsec_module;
|
103 | 103 |
|
| 104 | +struct url { |
| 105 | + const char *scheme; |
| 106 | + const char *authority; |
| 107 | + const char *path; |
| 108 | +}; |
| 109 | + |
104 | 110 | typedef struct
|
105 | 111 | {
|
106 | 112 | /* the url of the crowdsec service */
|
107 |
| - const char *url; |
| 113 | + struct url *url; |
108 | 114 | /* the API key of the crowdsec service */
|
109 | 115 | const char *key;
|
110 | 116 | /* shared obect cache mutex */
|
@@ -368,11 +374,11 @@ static int crowdsec_proxy(request_rec * r, const char **response)
|
368 | 374 | * filter that reads and parses the response from the API.
|
369 | 375 | */
|
370 | 376 |
|
371 |
| - const char *target = apr_pstrcat(r->pool, sconf->url, |
372 |
| - "/v1/decisions?ip=", |
373 |
| - ap_escape_urlencoded(r->pool, |
374 |
| - r->useragent_ip), |
375 |
| - NULL); |
| 377 | + char *api_path = "/v1/decisions?ip="; |
| 378 | + |
| 379 | + const char *target = apr_pstrcat( |
| 380 | + r->pool, sconf->url->scheme, "://", sconf->url->authority, api_path, |
| 381 | + ap_escape_urlencoded(r->pool, r->useragent_ip), NULL); |
376 | 382 |
|
377 | 383 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r,
|
378 | 384 | "crowdsec: looking up IP '%s' at url: %s",
|
@@ -865,14 +871,89 @@ static const char *set_crowdsec_location(cmd_parms *cmd, void *dconf,
|
865 | 871 | return NULL;
|
866 | 872 | }
|
867 | 873 |
|
| 874 | +// Note: url *must* be null-terminated |
| 875 | +struct url *find_base_lapi_url(apr_pool_t *pool, const char *url, |
| 876 | + const char **err) |
| 877 | +{ |
| 878 | + char *scheme = NULL; |
| 879 | + char *authority = NULL; |
| 880 | + apr_size_t authority_start_idx = 0; |
| 881 | + char *path = NULL; |
| 882 | + |
| 883 | + for (apr_size_t i = 0; url[i] != '\0'; i++) { |
| 884 | + if (!scheme) { |
| 885 | + if (url[i] == ':') { |
| 886 | + scheme = apr_pstrndup(pool, url, i); |
| 887 | + if (apr_cstr_casecmpn(url + i + 1, "//", 2)) { |
| 888 | + *err = |
| 889 | + "invalid lapi base url: \"//\" after scheme not found"; |
| 890 | + return NULL; |
| 891 | + } |
| 892 | + authority_start_idx = i + 3; |
| 893 | + i += 2; |
| 894 | + } |
| 895 | + continue; |
| 896 | + } |
| 897 | + if (!authority) { |
| 898 | + if (url[i] == '/') { |
| 899 | + authority = apr_pstrndup(pool, url + authority_start_idx, |
| 900 | + i - authority_start_idx); |
| 901 | + i--; |
| 902 | + } |
| 903 | + continue; |
| 904 | + } |
| 905 | + if (!path) { |
| 906 | + path = apr_pstrdup(pool, url + i); |
| 907 | + break; |
| 908 | + } |
| 909 | + } |
| 910 | + |
| 911 | + if (!scheme) { |
| 912 | + *err = "invalid lapi base url: scheme is missing"; |
| 913 | + return NULL; |
| 914 | + } |
| 915 | + |
| 916 | + if (!authority) { |
| 917 | + if (url[authority_start_idx] == '\0') { |
| 918 | + *err = "invalid lapi base url: authority is missing"; |
| 919 | + return NULL; |
| 920 | + } |
| 921 | + authority = apr_pstrdup(pool, url + authority_start_idx); |
| 922 | + } |
| 923 | + |
| 924 | + struct url *res = apr_palloc(pool, sizeof(struct url)); |
| 925 | + res->scheme = scheme; |
| 926 | + res->authority = authority; |
| 927 | + res->path = path; |
| 928 | + |
| 929 | + return res; |
| 930 | +} |
| 931 | + |
868 | 932 | static const char *set_crowdsec_url(cmd_parms * cmd, void *dconf,
|
869 | 933 | const char *url)
|
870 | 934 | {
|
871 | 935 | crowdsec_server_rec *sconf = (crowdsec_server_rec *)
|
872 | 936 | ap_get_module_config(cmd->server->module_config,
|
873 | 937 | &crowdsec_module);
|
874 | 938 |
|
875 |
| - sconf->url = url; |
| 939 | + const char *err = NULL; |
| 940 | + struct url *u = find_base_lapi_url(cmd->temp_pool, url, &err); |
| 941 | + if (err) { |
| 942 | + return err; |
| 943 | + } |
| 944 | + |
| 945 | + ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, sconf, |
| 946 | + "scheme: \"%s\", authority: \"%s\", path: \"%s\"", u->scheme, |
| 947 | + u->authority, u->path); |
| 948 | + if (u->path) { |
| 949 | + if (apr_strnatcmp(u->path, "/")) { |
| 950 | + ap_log_error(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, sconf, |
| 951 | + "lapi url: path (\"%s\") was found and will be ignored", |
| 952 | + u->path); |
| 953 | + } |
| 954 | + } |
| 955 | + |
| 956 | + sconf->url = u; |
876 | 957 | sconf->url_set = 1;
|
877 | 958 |
|
878 | 959 | return NULL;
|
|
0 commit comments