2
* (c) Software Lab. Alexander Burger
15
#include <arpa/inet.h>
17
#include <openssl/pem.h>
18
#include <openssl/ssl.h>
19
#include <openssl/err.h>
21
typedef enum {NO,YES} bool;
23
static char *File, *Dir, *Data;
27
"GET /%s HTTP/1.0\r\n"
28
"User-Agent: PicoLisp\r\n"
30
"Accept-Charset: utf-8\r\n\r\n";
32
static void errmsg(char *msg) {
33
fprintf(stderr, "ssl: %s\n", msg);
36
static void giveup(char *msg) {
41
static void sslChk(int n) {
43
ERR_print_errors_fp(stderr);
48
static int sslConnect(SSL *ssl, char *node, char *service) {
49
struct addrinfo hints, *lst, *p;
52
memset(&hints, 0, sizeof(hints));
53
hints.ai_family = AF_UNSPEC;
54
hints.ai_socktype = SOCK_STREAM;
55
if (getaddrinfo(node, service, &hints, &lst) == 0) {
56
for (p = lst; p; p = p->ai_next) {
57
if ((sd = socket(p->ai_family, p->ai_socktype, 0)) >= 0) {
58
if (connect(sd, p->ai_addr, p->ai_addrlen) == 0) {
61
if (SSL_connect(ssl) >= 0)
74
static void sslClose(SSL *ssl, int sd) {
79
static bool sslFile(SSL *ssl, char *file) {
84
return SSL_write(ssl, file+1, strlen(file)-1) >= 0;
85
if ((fd = open(file, O_RDONLY)) < 0)
87
while ((n = read(fd, buf, sizeof(buf))) > 0)
88
if (SSL_write(ssl, buf, n) < 0) {
96
static void doSigTerm(int n __attribute__((unused))) {
100
if (Data && (fd1 = open(File, O_RDWR)) >= 0) {
101
if (unlink(File) < 0)
102
giveup("Can't unlink back");
103
if ((fd2 = open(File, O_CREAT|O_WRONLY|O_TRUNC, 0666)) < 0)
104
giveup("Can't create back");
105
if (write(fd2, Data, Size) != Size)
106
giveup("Can't write back");
107
while ((cnt = read(fd1, buf, sizeof(buf))) > 0)
108
write(fd2, buf, cnt);
114
// ssl host port url file
115
// ssl host port url key file
116
// ssl host port url key file dir sec
117
int main(int ac, char *av[]) {
121
int n, sec, getLen, lenLen, fd, sd;
126
char get[1024], buf[4096], nm[4096], len[64];
128
if (!(ac >= 4 && ac <= 6 || ac == 8))
129
giveup("host port url [[key] file] | host port url key file dir sec");
130
if (strlen(Get)+strlen(av[1])+strlen(av[2])+strlen(av[3]) >= sizeof(get))
131
giveup("Names too long");
132
if (strchr(av[3],'/'))
133
bin = NO, getLen = sprintf(get, Get, av[3], av[1], av[2]);
135
bin = YES, getLen = sprintf(get, "@%s ", av[3]);
138
SSL_load_error_strings();
139
if (!(ctx = SSL_CTX_new(SSLv23_client_method()))) {
140
ERR_print_errors_fp(stderr);
146
if (sslConnect(ssl, av[1], av[2]) < 0) {
147
errmsg("Can't connect");
150
sslChk(SSL_write(ssl, get, getLen));
152
if (*av[4] && !sslFile(ssl,av[4]))
154
if (ac > 5 && *av[5] && !sslFile(ssl,av[5]))
157
while ((n = SSL_read(ssl, buf, sizeof(buf))) > 0)
158
write(STDOUT_FILENO, buf, n);
162
signal(SIGCHLD,SIG_IGN); /* Prevent zombies */
163
if ((n = fork()) < 0)
172
signal(SIGINT, doSigTerm);
173
signal(SIGTERM, doSigTerm);
174
signal(SIGPIPE, SIG_IGN);
176
if (*File && (fd = open(File, O_RDWR)) >= 0) {
177
if (fstat(fd,&st) < 0 || st.st_size == 0)
181
fl.l_whence = SEEK_SET;
184
if (fcntl(fd, F_SETLKW, &fl) < 0)
185
giveup("Can't lock");
186
if (fstat(fd,&st) < 0 || (Size = st.st_size) == 0)
187
giveup("Can't access");
188
lenLen = sprintf(len, "%lld\n", Size);
189
if ((Data = malloc(Size)) == NULL)
190
giveup("Can't alloc");
191
if (read(fd, Data, Size) != Size)
192
giveup("Can't read");
193
if (ftruncate(fd,0) < 0)
194
errmsg("Can't truncate");
197
if ((sd = sslConnect(ssl, av[1], av[2])) >= 0) {
198
if (SSL_write(ssl, get, getLen) == getLen &&
199
(!*av[4] || sslFile(ssl,av[4])) && // key
200
(bin || SSL_write(ssl, len, lenLen) == lenLen) && // length
201
SSL_write(ssl, Data, Size) == Size && // data
202
SSL_write(ssl, bin? "\0" : "T", 1) == 1 && // ack
203
SSL_read(ssl, buf, 1) == 1 && buf[0] == 'T' ) {
211
free(Data), Data = NULL;
214
if (*Dir && (dp = opendir(Dir))) {
215
while (p = readdir(dp)) {
216
if (p->d_name[0] != '.') {
217
snprintf(nm, sizeof(nm), "%s%s", Dir, p->d_name);
218
if ((n = readlink(nm, buf, sizeof(buf))) > 0 &&
219
(sd = sslConnect(ssl, av[1], av[2])) >= 0 ) {
220
if (SSL_write(ssl, get, getLen) == getLen &&
221
(!*av[4] || sslFile(ssl,av[4])) && // key
222
(bin || SSL_write(ssl, buf, n) == n) && // path
223
(bin || SSL_write(ssl, "\n", 1) == 1) && // nl
224
sslFile(ssl, nm) ) // file