Verify connect return code.
[cascardo/libreceita.git] / rnetclient.c
1 /*
2  *  Copyright (C) 2012  Thadeu Lima de Souza Cascardo <cascardo@minaslivre.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include <string.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <unistd.h>
24 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <arpa/inet.h>
27 #include <gnutls/gnutls.h>
28 #include <zlib.h>
29
30 static void * get_creds(char *certfile)
31 {
32         static gnutls_certificate_credentials_t cred;
33         gnutls_certificate_allocate_credentials(&cred);
34         gnutls_certificate_set_x509_trust_file(cred, certfile,
35                                         GNUTLS_X509_FMT_PEM);
36         return cred;
37 }
38
39 static void session_new(gnutls_session_t *session)
40 {
41         static void *cred;
42         cred = get_creds("cert.pem");
43         gnutls_init(session, GNUTLS_CLIENT);
44         gnutls_set_default_priority(*session);
45         gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE, cred);
46 }
47
48 static int deflateRecord(char *buffer, size_t len, char **out, size_t *olen)
49 {
50         z_stream zstrm;
51         int r;
52         zstrm.zalloc = Z_NULL;
53         zstrm.zfree = Z_NULL;
54         zstrm.opaque = Z_NULL;
55         if ((r = deflateInit(&zstrm, Z_DEFAULT_COMPRESSION)) != Z_OK)
56                 return -1;
57         *out = malloc(len * 2 + 36);
58         if (!out) {
59                 deflateEnd(&zstrm);
60                 return -1;
61         }
62         zstrm.next_in = buffer;
63         zstrm.avail_in = len;
64         zstrm.next_out = *out + 6;
65         zstrm.avail_out = len * 2 + 30;
66         while ((r = deflate(&zstrm, Z_FINISH)) != Z_STREAM_END &&
67                 zstrm.avail_out > 0);
68         if ((r = deflate(&zstrm, Z_FINISH)) != Z_STREAM_END) {
69                 deflateEnd(&zstrm);
70                 free(*out);
71                 return -1;
72         }
73         *olen = zstrm.avail_out + 6;
74         (*out)[0] = 0x1;
75         (*out)[1] = (zstrm.avail_out >> 8);
76         (*out)[2] = (zstrm.avail_out & 0xff);
77         (*out)[3] = (len >> 8);
78         (*out)[4] = (len & 0xff);
79         (*out)[5] = 0x1;
80         deflateEnd(&zstrm);
81         return 0;
82 }
83
84 static int inflateRecord(char *buffer, size_t len, char **out, size_t *olen)
85 {
86         z_stream zstrm;
87         int r;
88         zstrm.zalloc = Z_NULL;
89         zstrm.zfree = Z_NULL;
90         zstrm.opaque = Z_NULL;
91         if ((r = inflateInit(&zstrm)) != Z_OK)
92                 return -1;
93         *olen = (buffer[3] << 8 & buffer[4]);
94         *out = malloc(*olen);
95         if (!out) {
96                 inflateEnd(&zstrm);
97                 return -1;
98         }
99         zstrm.next_in = buffer + 6;
100         zstrm.avail_in = len - 6;
101         zstrm.next_out = *out;
102         zstrm.avail_out = *olen;
103         while ((r = inflate(&zstrm, Z_FINISH)) != Z_STREAM_END &&
104                 zstrm.avail_out > 0);
105         if ((r = inflate(&zstrm, Z_FINISH)) != Z_STREAM_END) {
106                 inflateEnd(&zstrm);
107                 free(*out);
108                 return -1;
109         }
110         inflateEnd(&zstrm);
111         return 0;
112 }
113
114 int main(int argc, char **argv)
115 {
116         struct sockaddr_in saddr;
117         int c;
118         int r;
119         char buffer[1024];
120         char *out;
121         size_t olen;
122         gnutls_session_t session;
123         gnutls_global_init();
124         session_new(&session);
125         c = socket(PF_INET, SOCK_STREAM, 0);
126         saddr.sin_family = AF_INET;
127         saddr.sin_port = htons(3456);
128         saddr.sin_addr.s_addr = inet_addr("161.148.185.140");
129         r = connect(c, (struct sockaddr *) &saddr, sizeof(saddr));
130         if (r < 0) {
131                 fprintf(stderr, "error connecting to server: %s\n",
132                         strerror(errno));
133                 exit(1);
134         }
135         gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) c);
136         buffer[0] = 1;
137         write(c, buffer, 1);
138         write(c, "00000000000000", 14);
139         r = read(c, buffer, 1);
140         if (r != 1 && buffer[0] != 'E')
141                 exit(1);
142         r = read(c, buffer, 14);
143         if (r != 14)
144                 exit(1);
145         if ((r = gnutls_handshake(session)) < 0)
146                 fprintf(stderr, "error in handshake: %s\n",
147                                 gnutls_strerror(r));
148         else
149                 fprintf(stderr, "handshake ok\n");
150         r = read(0, buffer, sizeof(buffer));
151         deflateRecord(buffer, r, &out, &olen);
152         gnutls_record_send(session, out, olen);
153         free(out);
154         while ((r = gnutls_record_recv(session, buffer, sizeof(buffer))) > 0)
155                 write(1, buffer, r);
156         close(c);
157         gnutls_global_deinit();
158         return 0;
159 }