From 757cb48d3606ef23192812a17a66b48c1ce2ea0f Mon Sep 17 00:00:00 2001 From: Wolfgang Kampichler Date: Sat, 1 Apr 2023 11:03:03 +0200 Subject: [PATCH] lost: additions to path element and corrected loop detection - LosT requests that allow recursion now include a element that contains one or more elements. A loop error is indicated if a returned target is already in the server list in the element. --- src/modules/lost/functions.c | 73 ++++++++++++++++++++++++++---------- src/modules/lost/response.c | 29 ++++++++++++++ src/modules/lost/response.h | 4 +- src/modules/lost/utilities.c | 62 +++++++++++++++++++++++++++++- src/modules/lost/utilities.h | 4 +- 5 files changed, 148 insertions(+), 24 deletions(-) diff --git a/src/modules/lost/functions.c b/src/modules/lost/functions.c index bc6dbd936cc..b7a2fe08872 100644 --- a/src/modules/lost/functions.c +++ b/src/modules/lost/functions.c @@ -819,7 +819,9 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, str req = STR_NULL; str con = STR_NULL; str ret = STR_NULL; + str src = STR_NULL; str pidf = STR_NULL; + str rereq = STR_NULL; str oldurl = STR_NULL; str losturl = STR_NULL; @@ -1063,9 +1065,8 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, goto err; } /* assemble findService request */ - req.s = lost_find_service_request(loc, &req.len); - lost_free_loc(&loc); /* clean up */ - + req.s = lost_find_service_request(loc, NULL, &req.len); + if(req.s == NULL && req.len == 0) { LM_ERR("lost request failed\n"); goto err; @@ -1113,7 +1114,7 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, LM_DBG("findService response: [%.*s]\n", ret.len, ret.s); - /* at least parse one request */ + /* at least parse one response */ redirect = 1; while(redirect) { fsrdata = lost_parse_findServiceResponse(ret); @@ -1186,6 +1187,39 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, tmp.len = strlen(fsrdata->redirect->target); url.s = &(ustr[0]); url.len = MAX_URI_SIZE; + /* check loop ... current response */ + if(oldurl.s != NULL && oldurl.len > 0) { + if(str_strcasecmp(&tmp, &oldurl) == 0) { + LM_ERR("loop detected: " + "[%.*s]<-->[%.*s]\n", + oldurl.len, oldurl.s, tmp.len, tmp.s); + goto err; + } + } + /* add redirecting source to path list */ + if((src.s = fsrdata->redirect->source) != NULL) { + src.len = strlen(fsrdata->redirect->source); + if(lost_append_response_list(&fsrdata->path, src) == 0) { + LM_ERR("could not append server to path elememt\n"); + goto err; + } + } + /* clean up */ + src.s = NULL; + src.len = 0; + /* check loop ... path elements */ + char *via = NULL; + if(lost_search_response_list(&fsrdata->path, &via, tmp.s) > 0) { + LM_ERR("loop detected: " + "[%s]<-->[%.*s]\n", + via, tmp.len, tmp.s); + goto err; + } + /* remember the redirect target */ + if(pkg_str_dup(&oldurl, &tmp) < 0) { + LM_ERR("could not copy: [%.*s]\n", tmp.len, tmp.s); + goto err; + } /* get url string via NAPTR */ naptr = lost_naptr_lookup(tmp, &shttps, &url); if(naptr == 0) { @@ -1200,23 +1234,15 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, /* clean up */ tmp.s = NULL; tmp.len = 0; - /* check loop */ - if(oldurl.s != NULL && oldurl.len > 0) { - if(str_strcasecmp(&url, &oldurl) == 0) { - LM_ERR("loop detected: " - "[%.*s]<-->[%.*s]\n", - oldurl.len, oldurl.s, url.len, url.s); - goto err; - } - } - /* remember the redirect target */ - if(pkg_str_dup(&oldurl, &url) < 0) { - LM_ERR("could not copy: [%.*s]\n", url.len, url.s); - goto err; - } + + /* assemble new findService request including path element */ + rereq.s = lost_find_service_request(loc, fsrdata->path, &rereq.len); /* clean up */ lost_free_findServiceResponse(&fsrdata); lost_free_string(&ret); + + LM_DBG("findService request: [%.*s]\n", rereq.len, rereq.s); + /* copy url */ len = 0; urlrep = lost_copy_string(url, &len); @@ -1226,9 +1252,12 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, } /* send request */ curl = httpapi.http_client_query( - _m, urlrep, &ret, req.s, mtlost); - pkg_free(urlrep); /*clean up */ + _m, urlrep, &ret, rereq.s, mtlost); + /*clean up */ + pkg_free(urlrep); urlrep = NULL; + lost_free_string(&rereq); + /* only HTTP 2xx responses are accepted */ if(curl >= 300 || curl < 100) { LM_ERR("POST [%.*s] failed with error: %d\n", @@ -1260,6 +1289,7 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, lost_free_string(&ret); lost_free_string(&req); lost_free_string(&oldurl); + lost_free_loc(&loc); /* set writable pvars */ pvname.rs = name; @@ -1310,6 +1340,9 @@ int lost_function(struct sip_msg *_m, char *_con, char *_uri, char *_name, if(req.s != NULL && req.len > 0) { lost_free_string(&req); } + if(rereq.s != NULL && rereq.len > 0) { + lost_free_string(&rereq); + } if(name.s != NULL && name.len > 0) { lost_free_string(&name); } diff --git a/src/modules/lost/response.c b/src/modules/lost/response.c index dcd6dc5363b..119d80a5028 100644 --- a/src/modules/lost/response.c +++ b/src/modules/lost/response.c @@ -353,6 +353,35 @@ void lost_reverse_response_list(p_lost_list_t *head) *head = prev; } +/* + * lost_append_response_list(list, str) + * appends str value to list object and returns str len + */ +int lost_append_response_list(p_lost_list_t *head, str val) +{ + int len = 0; + p_lost_list_t new = NULL; + p_lost_list_t current = *head; + + new = lost_new_response_list(); + if (new != NULL) { + new->value = lost_copy_string(val, &len); + new->next = NULL; + + LM_DBG("### new list data [%.*s]\n", val.len, val.s); + + if (current == NULL) { + *head = new; + return len; + } + while (current->next != NULL) { + current = current->next; + } + current->next = new; + } + return len; +} + /* * lost_search_response_list(list, value, search) * looks for search string in list object and returns pointer if found diff --git a/src/modules/lost/response.h b/src/modules/lost/response.h index 9c1fcbcb23a..9400f37a39a 100644 --- a/src/modules/lost/response.h +++ b/src/modules/lost/response.h @@ -121,7 +121,9 @@ typedef struct lost_fsr /* read and parse response data */ p_lost_fsr_t lost_parse_findServiceResponse(str); /* check response to dereferece request */ -int lost_check_HeldResponse(xmlNodePtr); +int lost_check_HeldResponse(xmlNodePtr); +/* appends value to list objects */ +int lost_append_response_list(p_lost_list_t *, str); /* print the response */ void lost_print_findServiceResponse(p_lost_fsr_t); /* remove response data from memory */ diff --git a/src/modules/lost/utilities.c b/src/modules/lost/utilities.c index c5fca4da3cd..f86fcaf0155 100644 --- a/src/modules/lost/utilities.c +++ b/src/modules/lost/utilities.c @@ -48,6 +48,7 @@ #include "pidf.h" #include "utilities.h" +#include "response.h" extern int lost_recursion; extern int lost_profile; @@ -1492,10 +1493,48 @@ char *lost_held_location_request(p_lost_held_t held, int *lgth) } /* - * lost_find_service_request(loc, lgth) + * lost_append_via_element(head, parent) + * appends via elements and returns the number of via elements added + */ +int lost_append_via_element(p_lost_list_t *head, xmlNodePtr *parent) +{ + int cnt = 0; + int i; + p_lost_list_t current = NULL; + + if (head == NULL) { + return 0; + } + + /* at least one element to add */ + current = *head; + cnt++; + + /* check for more elements to add */ + while (current->next != NULL) { + cnt++; + current = current->next; + } + + current = *head; + xmlNodePtr ptrVia[cnt]; + + /* ad elements to element */ + for (i = 0; i < cnt; i++) { + ptrVia[i] = xmlNewChild(*parent, NULL, BAD_CAST "via", NULL); + xmlNewProp(ptrVia[i], BAD_CAST "source", BAD_CAST current->value); + current = current->next; + } + + return cnt; +} + + +/* + * lost_find_service_request(loc, path, lgth) * assembles and returns findService request string (allocated in private memory) */ -char *lost_find_service_request(p_lost_loc_t loc, int *lgth) +char *lost_find_service_request(p_lost_loc_t loc, p_lost_list_t path, int *lgth) { int buffersize = 0; @@ -1511,6 +1550,7 @@ char *lost_find_service_request(p_lost_loc_t loc, int *lgth) xmlNodePtr ptrCircle = NULL; xmlNodePtr ptrRadius = NULL; xmlNodePtr ptrNode = NULL; + xmlNodePtr ptrPath = NULL; xmlKeepBlanksDefault(1); @@ -1531,6 +1571,10 @@ char *lost_find_service_request(p_lost_loc_t loc, int *lgth) urn:service:sos.police + + + + */ /* create request */ @@ -1623,6 +1667,20 @@ char *lost_find_service_request(p_lost_loc_t loc, int *lgth) /* service - element */ snprintf(buf, BUFSIZE, "%s", loc->urn); xmlNewChild(ptrFindService, NULL, BAD_CAST "service", BAD_CAST buf); + /* service - element */ + if (path != NULL) { + ptrPath = xmlNewChild(ptrFindService, NULL, BAD_CAST "path", NULL); + if(ptrPath == NULL) { + LM_ERR("locationRequest xmlNewChild() failed\n"); + xmlFreeDoc(request); + return doc; + } + if (lost_append_via_element(&path, &ptrPath) == 0) { + LM_ERR("appending elements to failed\n"); + xmlFreeDoc(request); + return doc; + } + } xmlDocDumpFormatMemory(request, &xmlbuff, &buffersize, 0); if(xmlbuff == NULL) { diff --git a/src/modules/lost/utilities.h b/src/modules/lost/utilities.h index f5802a28251..fc13599a80a 100644 --- a/src/modules/lost/utilities.h +++ b/src/modules/lost/utilities.h @@ -32,6 +32,8 @@ #ifndef LOST_UTILITIES_H #define LOST_UTILITIES_H +#include "response.h" + #define LAQUOT '<' #define COLON ':' @@ -132,7 +134,7 @@ int lost_parse_host(const char *, str *, int *); int lost_new_geoheader_list(p_lost_geolist_t *, str); int lost_get_nameinfo(char *, str *, int); -char *lost_find_service_request(p_lost_loc_t, int *); +char *lost_find_service_request(p_lost_loc_t, p_lost_list_t, int *); char *lost_held_location_request(p_lost_held_t, int *); char *lost_held_post_request(int *, long, char *); char *lost_get_content(xmlNodePtr, const char *, int *);