#include #include #include #include #include /* * If when a chunk is read into tmpbuf and the portion of the * response we are looking for, the answer, is truncated, parseres() * will either output the truncated answer or none at all. */ void parseres(BIO *sbio) { char tmpbuf[2048]; int len; char *ans; while ((len = BIO_read(sbio, tmpbuf, 2048)) > 0) { if ((ans = strstr(tmpbuf, "Your IP address is ")) == NULL) continue; printf("%s\n", strsep(&ans, "\"")); break; } } /* * Create connection to duckduckgo and make GET request query for * "what is my ip" with a json formatted response. * HTTP/1.0 in GET causes server to close connection automatically. */ BIO * makereq(SSL_CTX *ctx) { BIO *sbio; char *request = "GET /?q=what+is+my+ip&format=json&no_html=1" " HTTP/1.0\r\nHost: duckduckgo.com\r\n\r\n"; sbio = BIO_new_ssl_connect(ctx); if (sbio == NULL) err(1, "BIO_new_ssl_connect"); BIO_set_conn_hostname(sbio, "duckduckgo.com:https"); /* * BIO_do_connection and BIO_do_handshake are called * automatically from any I/O request (in this case BIO_puts) * and are here only for clarity */ if (BIO_do_connect(sbio) <= 0) err(1, "BIO_do_connect"); if (BIO_do_handshake(sbio) <= 0) err(1, "BIO_do_handshake"); BIO_puts(sbio, request); return sbio; } /* * make an https request to duckduckgo * query "what is my ip" * parse json response * write to stdout * TODO: verbose err strings */ int main() { SSL_CTX *ctx; BIO *sbio; SSL_library_init(); if ((ctx = SSL_CTX_new(TLS_client_method())) == NULL) err(1, "SSL_CTX_new"); sbio = makereq(ctx); parseres(sbio); BIO_free_all(sbio); SSL_CTX_free(ctx); return 0; }