Fix relative URI in GET request

This commit is contained in:
Suvendhu Hansa 2022-08-29 09:44:58 +00:00 committed by Vivek Kumar Dutta
parent 5553a890ae
commit 9f20db9d6d
4 changed files with 67 additions and 15 deletions

View file

@ -98,7 +98,7 @@ static int get_param_index(char *key)
return -1; return -1;
} }
static void strip_lead_trail_char(char *str, char ch) void strip_lead_trail_char(char *str, char ch)
{ {
/* First remove leading strip-char */ /* First remove leading strip-char */
const char* first_valid = str; const char* first_valid = str;
@ -366,9 +366,33 @@ int http_authentication_failure_resp(FILE *fp, const char *http_meth, const char
return 1; return 1;
} }
static void get_relative_path(const char *uri, const char *req_host, char *req_path, size_t size)
{
if (uri == NULL || req_path == NULL)
return;
memset(req_path, 0, size);
if (req_host == NULL || strlen(req_host) == 0) {
snprintf(req_path, size, "%s", uri);
return;
}
size_t host_len = strlen(req_host);
if (strncmp(uri, req_host, host_len) == 0) {
if (strlen(uri) == host_len) {
snprintf(req_path, size, "/");
} else {
snprintf(req_path, size, "%s", uri + strlen(req_host));
}
return;
}
snprintf(req_path, size, "%s", uri);
}
int validate_http_digest_auth(const char *http_meth, const char *uri, const char *hdr, int validate_http_digest_auth(const char *http_meth, const char *uri, const char *hdr,
const char *rlm, const char *usr, const char *psw, const char *rlm, const char *usr, const char *psw,
unsigned int timeout) unsigned int timeout, const char *req_host)
{ {
get_value_from_header(hdr); get_value_from_header(hdr);
@ -422,13 +446,22 @@ int validate_http_digest_auth(const char *http_meth, const char *uri, const char
if (strlen(param[E_URI].value) == 0) if (strlen(param[E_URI].value) == 0)
return 0; return 0;
if (strncmp(param[E_URI].value, uri, strlen(uri)) != 0) { CWMP_LOG(INFO, "Requested URI: (%s)", param[E_URI].value);
CWMP_LOG(ERROR, "Authentication failed, URI is not matched"); char req_path[2049] = {0};
get_relative_path(param[E_URI].value, req_host, req_path, sizeof(req_path));
if (strlen(req_path) == 0)
return 0;
CWMP_LOG(INFO, "Abs path: (%s)", req_path);
if (strncmp(req_path, uri, strlen(uri)) != 0) {
CWMP_LOG(ERROR, "Authentication failed, configured uri(%s), req path(%s) not matched", uri, req_path);
return 0; return 0;
} }
if ((strcmp(param[E_QOP].value, "auth") != 0) && (strcmp(param[E_QOP].value, "") != 0)) if ((strcmp(param[E_QOP].value, "auth") != 0) && (strcmp(param[E_QOP].value, "") != 0)) {
CWMP_LOG(ERROR, "Authentication failed, due to qop value: (%s)", param[E_QOP].value);
return 0; return 0;
}
char *tmp; char *tmp;
unsigned long int nc_int = strtoul(param[E_NC].value, &tmp, 16); unsigned long int nc_int = strtoul(param[E_NC].value, &tmp, 16);
@ -442,12 +475,17 @@ int validate_http_digest_auth(const char *http_meth, const char *uri, const char
char resp[MD5_HASH_HEX_LEN + 1]; char resp[MD5_HASH_HEX_LEN + 1];
get_digest_ha1("md5", usr, rlm, psw, param[E_NONCE].value, param[E_CNONCE].value, ha1, sizeof(ha1)); get_digest_ha1("md5", usr, rlm, psw, param[E_NONCE].value, param[E_CNONCE].value, ha1, sizeof(ha1));
get_digest_ha2(http_meth, uri, ha2, sizeof(ha2)); get_digest_ha2(http_meth, param[E_URI].value, ha2, sizeof(ha2));
get_digest_response(ha1, param[E_NONCE].value, param[E_NC].value, param[E_CNONCE].value, get_digest_response(ha1, param[E_NONCE].value, param[E_NC].value, param[E_CNONCE].value,
param[E_QOP].value, ha2, resp, sizeof(resp)); param[E_QOP].value, ha2, resp, sizeof(resp));
if (strcmp(resp, param[E_RESPONSE].value) != 0) if (strcmp(resp, param[E_RESPONSE].value) != 0) {
CWMP_LOG(ERROR, "Authentication failed due to response, rec(%s) calc(%s)", param[E_RESPONSE].value, resp);
CWMP_LOG(ERROR, "## received nonce:(%s) nc:(%s) usr:(%s)", param[E_NONCE].value, param[E_NC].value, usr);
CWMP_LOG(ERROR, "## rlm:(%s) psw:(%s) meth:(%s)", rlm, psw, http_meth);
CWMP_LOG(ERROR, "## cnonce:(%s)", param[E_CNONCE].value);
return 0; return 0;
}
return 1; return 1;
} }

View file

@ -16,9 +16,10 @@
extern char *nonce_key; extern char *nonce_key;
int get_nonce_key(void); int get_nonce_key(void);
void strip_lead_trail_char(char *str, char ch);
int validate_http_digest_auth(const char *http_meth, const char *uri, const char *hdr, int validate_http_digest_auth(const char *http_meth, const char *uri, const char *hdr,
const char *rlm, const char *usr, const char *psw, const char *rlm, const char *usr, const char *psw,
unsigned int timeout); unsigned int timeout, const char *req_host);
int http_authentication_failure_resp(FILE *fp, const char *http_meth, const char *uri, int http_authentication_failure_resp(FILE *fp, const char *http_meth, const char *uri,
const char *rlm, const char *opq); const char *rlm, const char *opq);

View file

@ -317,6 +317,7 @@ static void http_cr_new_client(int client, bool service_available)
bool auth_digest_checked = false; bool auth_digest_checked = false;
bool method_is_get = false; bool method_is_get = false;
bool internal_error = false; bool internal_error = false;
char request_host[2049] = {0};
char cr_http_get_head[HTTP_GET_HDR_LEN] = {0}; char cr_http_get_head[HTTP_GET_HDR_LEN] = {0};
@ -333,6 +334,11 @@ static void http_cr_new_client(int client, bool service_available)
} }
snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path); snprintf(cr_http_get_head, sizeof(cr_http_get_head), "GET %s HTTP/1.1", cwmp_main.conf.connection_request_path);
while (fgets(buffer, sizeof(buffer), fp)) { while (fgets(buffer, sizeof(buffer), fp)) {
if (buffer[0] == '\r' || buffer[0] == '\n') {
/* end of http request (empty line) */
break;
}
if (strstr(buffer, "GET ") != NULL && strstr(buffer, "HTTP/1.1") != NULL) { if (strstr(buffer, "GET ") != NULL && strstr(buffer, "HTTP/1.1") != NULL) {
// check if extra url parameter then ignore extra params // check if extra url parameter then ignore extra params
int j = 0; int j = 0;
@ -355,21 +361,23 @@ static void http_cr_new_client(int client, bool service_available)
method_is_get = true; method_is_get = true;
} }
strip_lead_trail_char(buffer, '\n');
strip_lead_trail_char(buffer, '\r');
if (!strncasecmp(buffer, "Authorization: Digest ", strlen("Authorization: Digest "))) { if (!strncasecmp(buffer, "Authorization: Digest ", strlen("Authorization: Digest "))) {
auth_digest_checked = true; auth_digest_checked = true;
CWMP_STRNCPY(auth_digest_buffer, buffer, BUFSIZ); CWMP_STRNCPY(auth_digest_buffer, buffer, BUFSIZ);
} }
if (buffer[0] == '\r' || buffer[0] == '\n') { if (strncasecmp(buffer, "Host: ", strlen("Host: ")) == 0 && strlen(buffer) > strlen("Host: ")) {
/* end of http request (empty line) */ snprintf(request_host, sizeof(request_host), "http://%s", buffer + strlen("Host: "));
break;
} }
} }
if (!service_available || !method_is_get) { if (!service_available || !method_is_get) {
goto http_end; goto http_end;
} }
int auth_check = validate_http_digest_auth("GET", cwmp_main.conf.connection_request_path, auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, 300); CWMP_LOG(INFO, "Received host: (%s)", request_host);
int auth_check = validate_http_digest_auth("GET", cwmp_main.conf.connection_request_path, auth_digest_buffer + strlen("Authorization: Digest "), REALM, username, password, 300, request_host);
if (auth_check == -1) { /* invalid nonce */ if (auth_check == -1) { /* invalid nonce */
internal_error = true; internal_error = true;
goto http_end; goto http_end;

View file

@ -101,26 +101,31 @@ int xml_handle_message(struct session *session)
} }
c = (char *)mxmlGetElement(b); c = (char *)mxmlGetElement(b);
if (c == NULL) {
CWMP_LOG(INFO, "Could not get element from received message");
goto error;
}
/* convert QName to localPart, check that ns is the expected one */ /* convert QName to localPart, check that ns is the expected one */
if (strchr(c, ':')) { if (strchr(c, ':')) {
char *tmp = strchr(c, ':'); char *tmp = strchr(c, ':');
size_t ns_len = tmp - c; size_t ns_len = tmp - c;
if (strlen(ns.cwmp) != ns_len) { if (strlen(ns.cwmp) != ns_len) {
CWMP_LOG(INFO, "Invalid received message"); CWMP_LOG(INFO, "Namespace length is not matched in string (%s) and expected (%s)", c, ns.cwmp);
session->fault_code = FAULT_CPE_REQUEST_DENIED; session->fault_code = FAULT_CPE_REQUEST_DENIED;
goto fault; goto fault;
} }
if (strncmp(ns.cwmp, c, ns_len)) { if (strncmp(ns.cwmp, c, ns_len)) {
CWMP_LOG(INFO, "Invalid received message"); CWMP_LOG(INFO, "Namespace in string (%s) is not the expected (%s) one", c, ns.cwmp);
session->fault_code = FAULT_CPE_REQUEST_DENIED; session->fault_code = FAULT_CPE_REQUEST_DENIED;
goto fault; goto fault;
} }
c = tmp + 1; c = tmp + 1;
} else { } else {
CWMP_LOG(INFO, "Invalid received message"); CWMP_LOG(INFO, "Can not convert QName to local part with received string (%s)", c);
session->fault_code = FAULT_CPE_REQUEST_DENIED; session->fault_code = FAULT_CPE_REQUEST_DENIED;
goto fault; goto fault;
} }