From 93d17e32d2c64a187bda4e4c7b0162072ab77c9c Mon Sep 17 00:00:00 2001 From: Nick White Date: Tue, 28 Jul 2015 16:20:28 +0100 Subject: Add SSL support using OpenSSL, and enable it for getgbook. This fixes the problem with getgbook not finding any books, and also obviously adds SSL, which is great! --- config.mk | 8 ++++-- getabook.c | 7 +++-- getbnbook.c | 7 +++-- getgbook.c | 9 +++--- util.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++-------------- util.h | 15 +++++++--- 6 files changed, 101 insertions(+), 37 deletions(-) diff --git a/config.mk b/config.mk index d366072..948e8b4 100644 --- a/config.mk +++ b/config.mk @@ -6,6 +6,8 @@ RELDATE = 2013-10-13 PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man +LIBS = -lssl -lcrypto + CFLAGS = -std=c99 -pedantic -Wall -Wextra -Werror -g -D_POSIX_C_SOURCE=200112L \ -DVERSION=\"$(VERSION)\" @@ -13,16 +15,16 @@ W32TCLKIT = tclkit-8.5.9-win32.upx.exe # glibc dynamic CC = cc -LDFLAGS = +LDFLAGS = $(LIBS) # musl static #CC = musl-gcc -#LDFLAGS = -static #-s +#LDFLAGS = $(LIBS) -static #-s # mingw #CC = i686-w64-mingw32-gcc #AR = i686-w64-mingw32-ar #CFLAGS = -ansi -Wall -DVERSION=\"$(VERSION)\" -DWINVER=0x0501 -#LDFLAGS = -lws2_32 +#LDFLAGS = $(LIBS) -lws2_32 LD = $(CC) diff --git a/getabook.c b/getabook.c index db4ca96..5f85143 100644 --- a/getabook.c +++ b/getabook.c @@ -15,6 +15,7 @@ " -n download pages from numbers in stdin\n" \ " otherwise, all available pages will be downloaded\n" +#define USESSL 0 #define URLMAX 1024 #define STRMAX 1024 #define MAXPAGES 9999 @@ -74,7 +75,7 @@ int getpagelist() snprintf(url, URLMAX, "/gp/search-inside/service-data?method=getBookData&asin=%s", bookid); - if(!get("www.amazon.com", url, NULL, NULL, &buf, 1)) + if(!get("www.amazon.com", USESSL, url, NULL, NULL, &buf, 1)) return 1; /* amazon have a canonical asin, which is needed to get all available pages */ @@ -132,7 +133,7 @@ int getpageurls(int pagenum) strncpy(url, "/gp/search-inside/service-data", URLMAX); snprintf(query, URLMAX, "method=goToPage&asin=%s&page=%d", bookid, pagenum); - if(!post("www.amazon.com", url, NULL, NULL, query, &buf, 1)) + if(!post("www.amazon.com", USESSL, url, NULL, NULL, query, &buf, 1)) return 1; fillurls(buf); @@ -158,7 +159,7 @@ int getpage(Page *page) return 1; } - if(gettofile(host, page->url, NULL, NULL, path, 0)) { + if(gettofile(host, USESSL, page->url, NULL, NULL, path, 0)) { fprintf(stderr, "%d failed\n", page->num); return 1; } diff --git a/getbnbook.c b/getbnbook.c index 6fa247f..a63416d 100644 --- a/getbnbook.c +++ b/getbnbook.c @@ -15,6 +15,7 @@ " -n download pages from numbers in stdin\n" \ " otherwise, all available pages will be downloaded\n" +#define USESSL 0 #define URLMAX 1024 #define STRMAX 1024 #define MAXPAGES 9999 @@ -38,7 +39,7 @@ int getpagelist() snprintf(url, URLMAX, "/DigBooks/viewer/bookviewmanager.aspx?op=getbookinfo&ean=%s", bookid); - if(!get("search2.barnesandnoble.com", url, cookies, NULL, &buf, 1)) + if(!get("search2.barnesandnoble.com", USESSL, url, cookies, NULL, &buf, 1)) return 1; /* find page url structure */ @@ -81,7 +82,7 @@ int getpage(int pagenum) s=strchr(urlpath+7, '/'); snprintf(pageurl, STRMAX, s, pagenum); - if(gettofile("search2.barnesandnoble.com", pageurl, cookies, NULL, path, 0)) { + if(gettofile("search2.barnesandnoble.com", USESSL, pageurl, cookies, NULL, path, 0)) { fprintf(stderr, "%d failed\n", pagenum); return 1; } @@ -113,7 +114,7 @@ int main(int argc, char *argv[]) bookdir = argv[argc-1]; /* get cookie */ - if(get("www.barnesandnoble.com", "/", NULL, cookies, &tmp, 0)) + if(get("www.barnesandnoble.com", USESSL, "/", NULL, cookies, &tmp, 0)) free(tmp); if(getpagelist()) { diff --git a/getgbook.c b/getgbook.c index e6e15af..5e36c04 100644 --- a/getgbook.c +++ b/getgbook.c @@ -16,6 +16,7 @@ " -n download pages from numbers in stdin\n" \ " otherwise, all available pages will be downloaded\n" +#define USESSL 1 #define URLMAX 1024 #define STRMAX 1024 #define MAXPAGES 9999 @@ -44,7 +45,7 @@ int getpagelist() snprintf(url, URLMAX, "/books?id=%s&printsec=frontcover&redir_esc=y", bookid); - if(!get("books.google.com", url, NULL, NULL, &buf, 1)) + if(!get("books.google.com", USESSL, url, NULL, NULL, &buf, 1)) return 1; if((s = strstr(buf, "_OC_Run({\"page\":[")) == NULL) @@ -83,7 +84,7 @@ int getpageurls(char *pagecode, char *cookie) snprintf(url, URLMAX, "/books?id=%s&pg=%s&jscmd=click3&q=subject:a&redir_esc=y", bookid, pagecode); - if(!get("books.google.com", url, cookie, NULL, &buf, 1)) + if(!get("books.google.com", USESSL, url, cookie, NULL, &buf, 1)) return 1; c = buf; @@ -137,7 +138,7 @@ int getpage(Page *page) return 1; } - if(gettofile("books.google.com", page->url, page->cookie, NULL, path, 0)) { + if(gettofile("books.google.com", USESSL, page->url, page->cookie, NULL, path, 0)) { fprintf(stderr, "%s failed\n", page->name); return 1; } @@ -188,7 +189,7 @@ int main(int argc, char *argv[]) /* get cookies */ for(i=0;ifd = -1; #ifdef WINVER WSADATA w; if(WSAStartup(MAKEWORD(2,2), &w)!= 0) { fprintf(stderr, "error: failed to start winsock\n"); - return -1; + return c; } #endif @@ -33,7 +36,7 @@ int dial(char *host, char *port) hints.ai_socktype = SOCK_STREAM; if(getaddrinfo(host, port, &hints, &res) != 0) { fprintf(stderr, "error: cannot resolve hostname %s\n", host); - return -1; + return c; } for(r = res; r; r = r->ai_next) { if((srv = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) == -1) @@ -45,31 +48,80 @@ int dial(char *host, char *port) freeaddrinfo(res); if(!r) { fprintf(stderr, "error: cannot connect to host %s\n", host); - return -1; + return c; } - return srv; + + c->fd = srv; + c->sslcontext = NULL; + c->sslhandle = NULL; + + if(ssl) { + SSL_load_error_strings(); + SSL_library_init(); + if((c->sslcontext = SSL_CTX_new(SSLv23_client_method())) == NULL) { + /*if((c->sslcontext = SSL_CTX_new(TLS_client_method())) == NULL) {*/ + ERR_print_errors_fp(stderr); + } + if((c->sslhandle = SSL_new(c->sslcontext)) == NULL) { + ERR_print_errors_fp(stderr); + } + if(SSL_set_fd(c->sslhandle, c->fd) != 1) { + ERR_print_errors_fp(stderr); + } + if(SSL_connect(c->sslhandle) != 1) { + ERR_print_errors_fp(stderr); + } + + } + return c; } -int request(char *host, char *request, char *savecookie, char **body, int istext) +int request(char *host, int ssl, char *request, char *savecookie, char **body, int istext) { size_t l, res; - int fd, i, p; + int i, p; char m[256]; - char c[COOKIEMAX] = ""; + char cookie[COOKIEMAX] = ""; + char port[4]; char *headpos; size_t headsize, bodysize; char headline[BUFSIZ] = ""; char *buf, *cur, *pos; + conn *c; - if((fd = dial(host, "80")) == -1) return 0; + if(ssl) { + strcpy(port, "443"); + } else { + strcpy(port, "80"); + } + c = dial(host, port, ssl); + if(c->fd == -1) { + return 0; + } - if(!send(fd, request, strlen(request), 0)) return 0; + if(ssl) { + if(!SSL_write(c->sslhandle, request, strlen(request))) { + ERR_print_errors_fp(stderr); + return 0; + } + } else { + if(!write(c->fd, request, strlen(request))) { + return 0; + } + } /* download everything into buf */ l = 0; buf = malloc(sizeof(char *) * BUFSIZ); - for(; buf != NULL && (res = recv(fd, buf+l, BUFSIZ, 0)) > 0; l+=res) - buf = realloc(buf, sizeof(char *) * (l+BUFSIZ)); + /* TODO: rewrite this so it's clear that only the read call differs, e.g. with + * macros as ii does it, or maybe as a function pointer or something */ + if(ssl) { + for(; buf != NULL && (res = SSL_read(c->sslhandle, buf+l, BUFSIZ)) > 0; l+=res) + buf = realloc(buf, sizeof(char *) * (l+BUFSIZ)); + } else { + for(; buf != NULL && (res = read(c->fd, buf+l, BUFSIZ)) > 0; l+=res) + buf = realloc(buf, sizeof(char *) * (l+BUFSIZ)); + } /* strstr to find end of header */ if((headpos = strstr(buf, "\r\n\r\n")) == NULL) { @@ -109,8 +161,8 @@ int request(char *host, char *request, char *savecookie, char **body, int istext return 0; } - if(savecookie != NULL && sscanf(headline, m, c)) { - strncat(savecookie, c, COOKIEMAX - strlen(savecookie) - 1); + if(savecookie != NULL && sscanf(headline, m, cookie)) { + strncat(savecookie, cookie, COOKIEMAX - strlen(savecookie) - 1); } } @@ -119,7 +171,7 @@ int request(char *host, char *request, char *savecookie, char **body, int istext return l; } -int get(char *host, char *path, char *sendcookie, char *savecookie, char **body, int istext) +int get(char *host, int ssl, char *path, char *sendcookie, char *savecookie, char **body, int istext) { char h[BUFSIZ] = ""; char c[COOKIEMAX] = ""; @@ -129,10 +181,10 @@ int get(char *host, char *path, char *sendcookie, char *savecookie, char **body, snprintf(h, BUFSIZ, "GET %s HTTP/1.0\r\nUser-Agent: getxbook-"VERSION \ " (not mozilla)\r\nHost: %s%s\r\n\r\n", path, host, c); - return request(host, h, savecookie, body, istext); + return request(host, ssl, h, savecookie, body, istext); } -int post(char *host, char *path, char *sendcookie, char *savecookie, char *data, char **body, int istext) +int post(char *host, int ssl, char *path, char *sendcookie, char *savecookie, char *data, char **body, int istext) { char h[BUFSIZ] = ""; char c[COOKIEMAX] = ""; @@ -145,16 +197,16 @@ int post(char *host, char *path, char *sendcookie, char *savecookie, char *data, "Host: %s%s\r\n\r\n%s\r\n", path, (int)strlen(data), host, c, data); - return request(host, h, savecookie, body, istext); + return request(host, ssl, h, savecookie, body, istext); } -int gettofile(char *host, char *url, char *sendcookie, char *savecookie, char *savepath, int istext) +int gettofile(char *host, int ssl, char *url, char *sendcookie, char *savecookie, char *savepath, int istext) { char *buf = 0; FILE *f; size_t i, l; - if(!(l = get(host, url, sendcookie, savecookie, &buf, istext))) { + if(!(l = get(host, ssl, url, sendcookie, savecookie, &buf, istext))) { fprintf(stderr, "Could not download %s\n", url); return 1; } diff --git a/util.h b/util.h index 6959ddc..a48a12e 100644 --- a/util.h +++ b/util.h @@ -1,7 +1,14 @@ /* See COPYING file for copyright and license details. */ #define COOKIEMAX 1024 -int dial(char *host, char *port); -int get(char *host, char *path, char *sendcookie, char *savecookie, char **body, int istext); -int post(char *host, char *path, char *sendcookie, char *savecookie, char *data, char **body, int istext); -int gettofile(char *host, char *url, char *sendcookie, char *savecookie, char *savepath, int istext); +#include +#include +typedef struct { + int fd; + SSL *sslhandle; + SSL_CTX *sslcontext; +} conn; +conn *dial(char *host, char *port, int ssl); +int get(char *host, int ssl, char *path, char *sendcookie, char *savecookie, char **body, int istext); +int post(char *host, int ssl, char *path, char *sendcookie, char *savecookie, char *data, char **body, int istext); +int gettofile(char *host, int ssl, char *url, char *sendcookie, char *savecookie, char *savepath, int istext); int renameifjpg(char *path); -- cgit v1.2.3