/** * Checks if given host is a known https host according to RFC 6797 8.2f */ static inline gboolean should_secure_host(HSTSProvider *provider, const char *host) { HSTSProviderPrivate *priv = HSTS_PROVIDER_GET_PRIVATE(provider); HSTSEntry *entry; char *canonical, *p; gboolean result = false, is_subdomain = false; /* ip is not allowed for hsts */ if (g_hostname_is_ip_address(host)) { return false; } canonical = g_hostname_to_ascii(host); /* don't match empty host */ if (*canonical) { p = canonical; /* Try to find the whole congruent matching host in hash table - if * not found strip of the first label and try to find a superdomain * match. Specified is a from right to left comparison 8.3, but in the * end this should be lead to the same result. */ while (p != NULL) { entry = g_hash_table_lookup(priv->whitelist, p); if (entry != NULL) { /* remove expired entries RFC 6797 8.1.1 */ if (soup_date_is_past(entry->expires_at)) { remove_host_entry(provider, p); } else if(!is_subdomain || entry->include_sub_domains) { result = true; break; } } is_subdomain = true; /* test without the first domain part */ if ((p = strchr(p, '.'))) { p++; } } } g_free(canonical); return result; }
static void print_request (SoupLogger *logger, SoupMessage *msg, SoupSession *session, SoupSocket *socket, gboolean restarted) { SoupLoggerPrivate *priv = SOUP_LOGGER_GET_PRIVATE (logger); SoupLoggerLogLevel log_level; SoupMessageHeadersIter iter; const char *name, *value; SoupURI *uri; if (priv->request_filter) { log_level = priv->request_filter (logger, msg, priv->request_filter_data); } else log_level = priv->level; if (log_level == SOUP_LOGGER_LOG_NONE) return; uri = soup_message_get_uri (msg); if (msg->method == SOUP_METHOD_CONNECT) { soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', "CONNECT %s:%u HTTP/1.%d", uri->host, uri->port, soup_message_get_http_version (msg)); } else { soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', "%s %s%s%s HTTP/1.%d", msg->method, uri->path, uri->query ? "?" : "", uri->query ? uri->query : "", soup_message_get_http_version (msg)); } soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', "Soup-Debug-Timestamp: %lu", (unsigned long)time (0)); soup_logger_print (logger, SOUP_LOGGER_LOG_MINIMAL, '>', "Soup-Debug: %s %u (%p), %s %u (%p), %s %u (%p)%s", g_type_name_from_instance ((GTypeInstance *)session), soup_logger_get_id (logger, session), session, g_type_name_from_instance ((GTypeInstance *)msg), soup_logger_get_id (logger, msg), msg, g_type_name_from_instance ((GTypeInstance *)socket), soup_logger_get_id (logger, socket), socket, restarted ? ", restarted" : ""); if (log_level == SOUP_LOGGER_LOG_MINIMAL) return; if (!soup_message_headers_get_one (msg->request_headers, "Host")) { char *uri_host; if (strchr (uri->host, ':')) uri_host = g_strdup_printf ("[%s]", uri->host); else if (g_hostname_is_non_ascii (uri->host)) uri_host = g_hostname_to_ascii (uri->host); else uri_host = uri->host; soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', "Host: %s%c%u", uri_host, soup_uri_uses_default_port (uri) ? '\0' : ':', uri->port); if (uri_host != uri->host) g_free (uri_host); } soup_message_headers_iter_init (&iter, msg->request_headers); while (soup_message_headers_iter_next (&iter, &name, &value)) { if (!g_ascii_strcasecmp (name, "Authorization") && !g_ascii_strncasecmp (value, "Basic ", 6)) soup_logger_print_basic_auth (logger, value); else { soup_logger_print (logger, SOUP_LOGGER_LOG_HEADERS, '>', "%s: %s", name, value); } } if (log_level == SOUP_LOGGER_LOG_HEADERS) return; if (msg->request_body->length && soup_message_body_get_accumulate (msg->request_body)) { SoupBuffer *request; request = soup_message_body_flatten (msg->request_body); g_return_if_fail (request != NULL); soup_buffer_free (request); if (soup_message_headers_get_expectations (msg->request_headers) != SOUP_EXPECTATION_CONTINUE) { soup_logger_print (logger, SOUP_LOGGER_LOG_BODY, '>', "\n%s", msg->request_body->data); } } }
/* "Add domain"-button was pressed */ static void _nojs_preferences_on_add_domain_clicked(NoJSPreferences *self, gpointer *inUserData) { NoJSPreferencesPrivate *priv=self->priv; gchar *domain; const gchar *domainStart, *domainEnd; gchar *realDomain; GtkTreeIter policyIter; g_return_if_fail(priv->database); /* Get domain name entered */ domain=g_hostname_to_ascii(gtk_entry_get_text(GTK_ENTRY(priv->addDomainEntry))); /* Trim whitespaces from start and end of entered domain name */ domainStart=domain; while(*domainStart && g_ascii_isspace(*domainStart)) domainStart++; domainEnd=domain+strlen(domain)-1; while(*domainEnd && g_ascii_isspace(*domainEnd)) domainEnd--; if(domainEnd<=domainStart) return; /* Seperate domain name from whitespaces */ realDomain=g_strndup(domain, domainEnd-domainStart+1); if(!realDomain) return; /* Get policy from combo box */ if(gtk_combo_box_get_active_iter(GTK_COMBO_BOX(priv->addDomainPolicyCombo), &policyIter)) { gchar *sql; gchar *error=NULL; gint success; gint policy; gchar *policyName; /* Get policy value to set for domain */ gtk_tree_model_get(gtk_combo_box_get_model(GTK_COMBO_BOX(priv->addDomainPolicyCombo)), &policyIter, 0, &policy, 1, &policyName, -1); /* Add domain name and the selected policy to database */ sql=sqlite3_mprintf("INSERT OR REPLACE INTO policies (site, value) VALUES ('%q', %d);", realDomain, policy); success=sqlite3_exec(priv->database, sql, NULL, NULL, &error); /* Show error message if any */ if(success==SQLITE_OK) { gtk_list_store_append(priv->listStore, &policyIter); gtk_list_store_set(priv->listStore, &policyIter, DOMAIN_COLUMN, realDomain, POLICY_COLUMN, policyName, -1); } else g_warning(_("SQL fails: %s"), error); if(error) sqlite3_free(error); /* Free allocated resources */ sqlite3_free(sql); } /* Free allocated resources */ g_free(realDomain); g_free(domain); }
/* Entry containing domain name which may be added to list has changed */ static void _nojs_preferences_on_add_domain_entry_changed(NoJSPreferences *self, GtkEditable *inEditable) { NoJSPreferencesPrivate *priv=self->priv; gchar *asciiDomain, *checkAsciiDomain; gchar *asciiDomainStart, *asciiDomainEnd; gint dots; gboolean isValid=FALSE; /* Get ASCII representation of domain name entered */ asciiDomain=g_hostname_to_ascii(gtk_entry_get_text(GTK_ENTRY(priv->addDomainEntry))); /* Trim whitespaces from start and end of entered domain name */ asciiDomainStart=asciiDomain; while(*asciiDomainStart && g_ascii_isspace(*asciiDomainStart)) asciiDomainStart++; asciiDomainEnd=asciiDomain+strlen(asciiDomain)-1; while(*asciiDomainEnd && g_ascii_isspace(*asciiDomainEnd)) asciiDomainEnd--; /* We allow only domain names and not cookie domain name so entered name * must not start with a dot */ checkAsciiDomain=asciiDomainStart; isValid=(*asciiDomainStart!='.' && *asciiDomainEnd!='.'); /* Now check if ASCII domain name is valid (very very simple check) * and contains a hostname besides TLD */ dots=0; while(*checkAsciiDomain && checkAsciiDomain<=asciiDomainEnd && isValid) { /* Check for dot as (at least the first one) seperates hostname from TLD */ if(*checkAsciiDomain=='.') dots++; else { /* Check for valid characters in domain name. * Valid domain name can only contain ASCII alphabetic letters, * digits (0-9) and hyphens ('-') */ isValid=(g_ascii_isalpha(*checkAsciiDomain) || g_ascii_isdigit(*checkAsciiDomain) || *checkAsciiDomain=='-'); } checkAsciiDomain++; } /* If we have not reached the trimmed end of string something must have gone wrong * and domain entered is invalid. If domain name entered excluding dots is longer * than 255 character it is also invalid. */ if(checkAsciiDomain<asciiDomainEnd) isValid=FALSE; else if((checkAsciiDomain-asciiDomainStart-dots)>255) isValid=FALSE; /* We need at least one dot in domain name (minimum number of dots to seperate * hostname from TLD) */ isValid=(isValid && dots>0); /* Activate "add" button if hostname (equal to domain name here) is valid */ gtk_widget_set_sensitive(priv->addDomainButton, isValid); /* Free allocated resources */ g_free(asciiDomain); }
static void get_request_headers (SoupMessage *req, GString *header, SoupEncoding *encoding, gpointer user_data) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); SoupMessageQueueItem *item = user_data; SoupURI *uri = soup_message_get_uri (req); char *uri_host; char *uri_string; SoupMessageHeadersIter iter; const char *name, *value; if (strchr (uri->host, ':')) uri_host = g_strdup_printf ("[%s]", uri->host); else if (g_hostname_is_non_ascii (uri->host)) uri_host = g_hostname_to_ascii (uri->host); else uri_host = uri->host; if (req->method == SOUP_METHOD_CONNECT) { /* CONNECT URI is hostname:port for tunnel destination */ uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port); } else { gboolean proxy = soup_connection_is_via_proxy (item->conn); /* Proxy expects full URI to destination. Otherwise * just the path. */ uri_string = soup_uri_to_string (uri, !proxy); if (proxy && uri->fragment) { /* Strip fragment */ char *fragment = strchr (uri_string, '#'); if (fragment) *fragment = '\0'; } } if (priv->http_version == SOUP_HTTP_1_0) { g_string_append_printf (header, "%s %s HTTP/1.0\r\n", req->method, uri_string); } else { g_string_append_printf (header, "%s %s HTTP/1.1\r\n", req->method, uri_string); if (!soup_message_headers_get_one (req->request_headers, "Host")) { if (soup_uri_uses_default_port (uri)) { g_string_append_printf (header, "Host: %s\r\n", uri_host); } else { g_string_append_printf (header, "Host: %s:%d\r\n", uri_host, uri->port); } } } g_free (uri_string); if (uri_host != uri->host) g_free (uri_host); *encoding = soup_message_headers_get_encoding (req->request_headers); if ((*encoding == SOUP_ENCODING_CONTENT_LENGTH || *encoding == SOUP_ENCODING_NONE) && (req->request_body->length > 0 || soup_message_headers_get_one (req->request_headers, "Content-Type")) && !soup_message_headers_get_content_length (req->request_headers)) { *encoding = SOUP_ENCODING_CONTENT_LENGTH; soup_message_headers_set_content_length (req->request_headers, req->request_body->length); } soup_message_headers_iter_init (&iter, req->request_headers); while (soup_message_headers_iter_next (&iter, &name, &value)) g_string_append_printf (header, "%s: %s\r\n", name, value); g_string_append (header, "\r\n"); }