Example #1
0
void CToxProto::SearchByNameAsync(void *arg)
{
	char *query = (char*)arg;
	char *name = strtok(query, "@");
	char *domain = strtok(NULL, "");

	int resolved = 0;

	if (IsFileExists((TCHAR*)VARST(_T(TOX_INI_PATH))))
	{
		char fileName[MAX_PATH];
		mir_strcpy(fileName, VARS(TOX_INI_PATH));

		char *section, sections[MAX_PATH], value[TOX_PUBLIC_KEY_SIZE * 2];
		GetPrivateProfileSectionNamesA(sections, _countof(sections), fileName);
		section = sections;
		while (*section != NULL)
		{
			if (strstr(section, "Dns_") == section)
			{
				GetPrivateProfileStringA(section, "Domain", NULL, value, _countof(value), fileName);
				ptrA dnsDomain(mir_strdup(value));
				GetPrivateProfileStringA(section, "PubKey", NULL, value, _countof(value), fileName);
				ToxBinAddress dnsPubKey = value;

				if (domain == NULL || mir_strcmpi(domain, dnsDomain) == 0)
				{
					void *dns = tox_dns3_new((uint8_t*)(const uint8_t*)dnsPubKey);

					uint32_t requestId = 0;
					uint8_t dnsString[MAX_PATH];
					size_t length = tox_generate_dns3_string(dns, dnsString, sizeof(dnsString), &requestId, (uint8_t*)CharLowerA(name), (uint8_t)mir_strlen(name));
					if (length != TOX_ERROR)
					{
						dnsString[length] = 0;
						char dnsQuery[MAX_PATH * 2];
						mir_snprintf(dnsQuery, "_%s._tox.%s", dnsString, dnsDomain);

						ToxHexAddress address = ResolveToxAddressFromDns(dnsQuery);
						if (!address.IsEmpty())
						{
							PROTOSEARCHRESULT psr = { sizeof(PROTOSEARCHRESULT) };
							psr.flags = PSR_UTF8;
							psr.id.a = mir_strdup(address);
							psr.nick.a = mir_strdup(name);

							char email[MAX_PATH];
							mir_snprintf(email, "%s@%s", name, domain);
							psr.email.a = mir_strdup(email);

							ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, (LPARAM)&psr);
							break;
						}
					}
					tox_dns3_kill(dns);
				}
			}
			section += mir_strlen(section) + 1;
		}
	}

	if (resolved == 0 && domain)
	{
		char dnsQuery[MAX_PATH];
		mir_snprintf(dnsQuery, "%s._tox.%s", name, domain);

		ToxHexAddress address = ResolveToxAddressFromDns(dnsQuery);
		if (!address.IsEmpty())
		{
			PROTOSEARCHRESULT psr = { sizeof(PROTOSEARCHRESULT) };
			psr.flags = PSR_UTF8;
			psr.id.a = mir_strdup(address);
			psr.nick.a = mir_strdup(name);

			char email[MAX_PATH];
			mir_snprintf(email, "%s@%s", name, domain);
			psr.email.a = mir_strdup(email);

			ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)1, (LPARAM)&psr);
		}
	}

	ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)1, 0);
	mir_free(arg);
}
Example #2
0
QString ToxDNS::queryTox3(const tox3_server& server, const QString &record, bool silent)
{
    QByteArray nameData = record.left(record.indexOf('@')).toUtf8(), id, realRecord;
    QString entry, toxIdStr;
    int toxIdSize, idx, verx, dns_string_len;
    const int dns_string_maxlen = 128;

    void* tox_dns3 = tox_dns3_new(server.pubkey);
    if (!tox_dns3)
    {
        qWarning() << "failed to create a tox_dns3 object for "<<server.name<<", using tox1 as a fallback";
        goto fallbackOnTox1;
    }
    uint32_t request_id;
    uint8_t dns_string[dns_string_maxlen];
    dns_string_len = tox_generate_dns3_string(tox_dns3, dns_string, dns_string_maxlen, &request_id,
                             (uint8_t*)nameData.data(), nameData.size());

    if (dns_string_len < 0) // We can always fallback on tox1 if toxdns3 fails
    {
        qWarning() << "failed to generate dns3 string for "<<server.name<<", using tox1 as a fallback";
        goto fallbackOnTox1;
    }

    realRecord = '_'+QByteArray((char*)dns_string, dns_string_len)+"._tox."+server.name;
    entry = fetchLastTextRecord(realRecord, silent);
    if (entry.isEmpty())
    {
        qWarning() << "Server "<<server.name<<" returned no record, assuming the Tox ID doesn't exist";
        return toxIdStr;
    }

    // Check toxdns protocol version
    verx = entry.indexOf("v=");
    if (verx!=-1)
    {
        verx += 2;
        int verend = entry.indexOf(';', verx);
        if (verend!=-1)
        {
            QString ver = entry.mid(verx, verend-verx);
            if (ver != "tox3")
            {
                qWarning() << "Server "<<server.name<<" returned a bad version ("<<ver<<"), using tox1 as a fallback";
                goto fallbackOnTox1;
            }
        }
    }

    // Get and decrypt the tox id
    idx = entry.indexOf("id=");
    if (idx < 0)
    {
        qWarning() << "Server "<<server.name<<" returned an empty id, using tox1 as a fallback";
        goto fallbackOnTox1;
    }

    idx += 3;
    id = entry.mid(idx).toUtf8();
    uint8_t toxId[TOX_ADDRESS_SIZE];
    toxIdSize = tox_decrypt_dns3_TXT(tox_dns3, toxId, (uint8_t*)id.data(), id.size(), request_id);
    if (toxIdSize < 0) // We can always fallback on tox1 if toxdns3 fails
    {
        qWarning() << "Failed to decrypt dns3 reply for "<<server.name<<", using tox1 as a fallback";
        goto fallbackOnTox1;
    }

    tox_dns3_kill(tox_dns3);
    toxIdStr = CFriendAddress::toString(toxId);
    return toxIdStr;

    // Centralized error handling, fallback on tox1 queries
fallbackOnTox1:
    if (tox_dns3)
        tox_dns3_kill(tox_dns3);

#if TOX1_SILENT_FALLBACK
    toxIdStr = queryTox1(record, silent);
#elif TOX1_ASK_FALLBACK
    QMessageBox::StandardButton btn =
        QMessageBox::warning(nullptr, "qTox",
                             tr("It appears that qTox has to use the old protocol to access DNS record of your friend's Tox ID.\n"
                                "Unfortunately tox1 is not secure, and you are at risk of someone hijacking what is sent between you and ToxDNS service.\n"
                                "Should tox1 be used anyway?\n"
                                "If unsure, press 'No', so that request to ToxDNS service will not be made using unsecure protocol."),
                                QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
    if (btn == QMessageBox::Yes)
        queryTox1(record, silent);

#endif
    return toxIdStr;
}
Example #3
0
File: dns.c Project: jpoler/toxic
/* Does DNS lookup for addr and puts resulting tox id in id_bin. */
void *dns3_lookup_thread(void *data)
{
    ToxWindow *self = t_data.self;

    char inputdomain[MAX_STR_SIZE];
    char name[MAX_STR_SIZE];

    int namelen = parse_addr(t_data.addr, name, inputdomain);

    if (namelen == -1) {
        dns_error(self, "Must be a Tox ID or an address in the form username@domain");
        killdns_thread(NULL);
    }

    char DNS_pubkey[DNS3_KEY_SIZE];
    char domain[MAX_DOMAIN_SIZE];

    int match = get_domain_match(DNS_pubkey, domain, inputdomain);

    if (match == -1) {
        dns_error(self, "Domain not found.");
        killdns_thread(NULL);
    }

    void *dns_obj = tox_dns3_new((uint8_t *) DNS_pubkey);

    if (dns_obj == NULL) {
        dns_error(self, "Core failed to create DNS object.");
        killdns_thread(NULL);
    }

    char string[MAX_DNS_REQST_SIZE + 1];
    uint32_t request_id;

    int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id, 
                                           (uint8_t *) name, namelen);

    if (str_len == -1) {
        dns_error(self, "Core failed to generate DNS3 string.");
        killdns_thread(dns_obj);
    }

    string[str_len] = '\0';

    u_char answer[PACKETSZ];
    char d_string[MAX_DOMAIN_SIZE + MAX_DNS_REQST_SIZE + 10];

    /* format string and create dns query */
    snprintf(d_string, sizeof(d_string), "_%s._tox.%s", string, domain);
    int ans_len = res_query(d_string, C_IN, T_TXT, answer, sizeof(answer));

    if (ans_len <= 0) {
        dns_error(self, "DNS query failed.");
        killdns_thread(dns_obj);
    }

    char ans_id[MAX_DNS_REQST_SIZE + 1];

    /* extract TXT from DNS response */
    if (parse_dns_response(self, answer, ans_len, ans_id) == -1)
        killdns_thread(dns_obj);

    char encrypted_id[MAX_DNS_REQST_SIZE + 1];
    int prfx_len = strlen(TOX_DNS3_TXT_PREFIX);

    /* extract the encrypted ID from TXT response */
    if (strncmp(ans_id, TOX_DNS3_TXT_PREFIX, prfx_len) != 0) {
        dns_error(self, "Bad DNS3 TXT response.");
        killdns_thread(dns_obj);
    }

    memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len);

    if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id, 
                             strlen(encrypted_id), request_id) == -1) {
        dns_error(self, "Core failed to decrypt DNS response.");
        killdns_thread(dns_obj);
    }

    pthread_mutex_lock(&Winthread.lock);
    cmd_add_helper(self, t_data.m, t_data.id_bin, t_data.msg);
    pthread_mutex_unlock(&Winthread.lock);

    killdns_thread(dns_obj);
    return 0;
}