diff options
Diffstat (limited to 'libraries/ecore/src/examples/ecore_fd_handler_gnutls_example.c')
-rw-r--r-- | libraries/ecore/src/examples/ecore_fd_handler_gnutls_example.c | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/libraries/ecore/src/examples/ecore_fd_handler_gnutls_example.c b/libraries/ecore/src/examples/ecore_fd_handler_gnutls_example.c new file mode 100644 index 0000000..b67e04e --- /dev/null +++ b/libraries/ecore/src/examples/ecore_fd_handler_gnutls_example.c | |||
@@ -0,0 +1,195 @@ | |||
1 | #include <Ecore.h> | ||
2 | #include <fcntl.h> | ||
3 | #include <netinet/tcp.h> | ||
4 | #include <netinet/in.h> | ||
5 | #include <sys/socket.h> | ||
6 | #include <arpa/inet.h> | ||
7 | #include <errno.h> | ||
8 | #include <unistd.h> | ||
9 | #include <gnutls/gnutls.h> | ||
10 | |||
11 | /* Ecore_Fd_Handler example | ||
12 | * 2010 Mike Blumenkrantz | ||
13 | * compile with gcc $(pkgconfig --cflags --libs gnutls ecore) | ||
14 | */ | ||
15 | |||
16 | |||
17 | #define print(...) fprintf(stderr, "line %i: ", __LINE__); fprintf(stderr, __VA_ARGS__); fprintf(stderr, "\n") | ||
18 | |||
19 | static int done = 0; | ||
20 | |||
21 | static void | ||
22 | tls_log_func (int level, const char *str) | ||
23 | { | ||
24 | fprintf(stderr, "|<%d>| %s", level, str); | ||
25 | } | ||
26 | |||
27 | static const char* | ||
28 | SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_description_t status) | ||
29 | { | ||
30 | switch (status) | ||
31 | { | ||
32 | case GNUTLS_HANDSHAKE_HELLO_REQUEST: | ||
33 | return "Hello request"; | ||
34 | case GNUTLS_HANDSHAKE_CLIENT_HELLO: | ||
35 | return "Client hello"; | ||
36 | case GNUTLS_HANDSHAKE_SERVER_HELLO: | ||
37 | return "Server hello"; | ||
38 | case GNUTLS_HANDSHAKE_CERTIFICATE_PKT: | ||
39 | return "Certificate packet"; | ||
40 | case GNUTLS_HANDSHAKE_SERVER_KEY_EXCHANGE: | ||
41 | return "Server key exchange"; | ||
42 | case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST: | ||
43 | return "Certificate request"; | ||
44 | case GNUTLS_HANDSHAKE_SERVER_HELLO_DONE: | ||
45 | return "Server hello done"; | ||
46 | case GNUTLS_HANDSHAKE_CERTIFICATE_VERIFY: | ||
47 | return "Certificate verify"; | ||
48 | case GNUTLS_HANDSHAKE_CLIENT_KEY_EXCHANGE: | ||
49 | return "Client key exchange"; | ||
50 | case GNUTLS_HANDSHAKE_FINISHED: | ||
51 | return "Finished"; | ||
52 | case GNUTLS_HANDSHAKE_SUPPLEMENTAL: | ||
53 | return "Supplemental"; | ||
54 | } | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | /* Connects to the peer and returns a socket | ||
59 | * descriptor. | ||
60 | */ | ||
61 | static int | ||
62 | tcp_connect (void) | ||
63 | { | ||
64 | const char *PORT = "443"; | ||
65 | const char *SERVER = "69.58.181.89"; //verisign.com | ||
66 | int err, sd; | ||
67 | int flag = 1, curstate = 0; | ||
68 | struct sockaddr_in sa; | ||
69 | |||
70 | /* sets some fd options such as nonblock */ | ||
71 | sd = socket (AF_INET, SOCK_STREAM, 0); | ||
72 | fcntl(sd, F_SETFL, O_NONBLOCK); | ||
73 | fcntl(sd, F_SETFD, FD_CLOEXEC); | ||
74 | setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (const void *)&curstate, sizeof(curstate)); | ||
75 | |||
76 | setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int)); | ||
77 | |||
78 | memset (&sa, '\0', sizeof (sa)); | ||
79 | sa.sin_family = AF_INET; | ||
80 | sa.sin_port = htons (atoi (PORT)); | ||
81 | inet_pton (AF_INET, SERVER, &sa.sin_addr); | ||
82 | |||
83 | /* connects to server | ||
84 | */ | ||
85 | err = connect (sd, (struct sockaddr *) &sa, sizeof (sa)); | ||
86 | if ((err < 0) && (errno != EINPROGRESS)) | ||
87 | { | ||
88 | print("Connect error\n"); | ||
89 | exit (1); | ||
90 | } | ||
91 | |||
92 | return sd; | ||
93 | } | ||
94 | |||
95 | /* closes the given socket descriptor. | ||
96 | */ | ||
97 | static void | ||
98 | tcp_close (int sd) | ||
99 | { | ||
100 | shutdown (sd, SHUT_RDWR); /* no more receptions */ | ||
101 | close (sd); | ||
102 | } | ||
103 | |||
104 | static Eina_Bool | ||
105 | _process_data(gnutls_session_t client, Ecore_Fd_Handler *fd_handler) | ||
106 | { | ||
107 | static int ret, lastret; | ||
108 | static unsigned int count = 0; | ||
109 | |||
110 | if (!done) | ||
111 | { | ||
112 | lastret = ret; | ||
113 | ret = gnutls_handshake (client); | ||
114 | count++; | ||
115 | if (gnutls_record_get_direction(client)) | ||
116 | ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_WRITE); | ||
117 | else | ||
118 | ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_READ); | ||
119 | /* avoid printing messages infinity times */ | ||
120 | if (lastret != ret) | ||
121 | { | ||
122 | print("gnutls returned with: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret)); | ||
123 | if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) | ||
124 | print("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(client))); | ||
125 | print("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(client))); | ||
126 | print("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(client))); | ||
127 | } | ||
128 | |||
129 | if (gnutls_error_is_fatal(ret)) | ||
130 | { | ||
131 | print("yarrr this be an error!"); | ||
132 | exit(1); | ||
133 | } | ||
134 | |||
135 | } | ||
136 | if (ret == GNUTLS_E_SUCCESS) | ||
137 | { | ||
138 | done = 1; | ||
139 | print("Handshake successful in %u handshake calls!", count); | ||
140 | ecore_main_loop_quit(); | ||
141 | } | ||
142 | |||
143 | return ECORE_CALLBACK_RENEW; | ||
144 | } | ||
145 | |||
146 | int | ||
147 | main (void) | ||
148 | { | ||
149 | /* credentials */ | ||
150 | gnutls_anon_client_credentials_t c_anoncred; | ||
151 | gnutls_certificate_credentials_t c_certcred; | ||
152 | |||
153 | gnutls_session_t client; | ||
154 | int sd; | ||
155 | |||
156 | /* General init. */ | ||
157 | gnutls_global_init (); | ||
158 | ecore_init(); | ||
159 | gnutls_global_set_log_function (tls_log_func); | ||
160 | gnutls_global_set_log_level (6); | ||
161 | |||
162 | /* Init client */ | ||
163 | gnutls_anon_allocate_client_credentials (&c_anoncred); | ||
164 | gnutls_certificate_allocate_credentials (&c_certcred); | ||
165 | gnutls_init (&client, GNUTLS_CLIENT); | ||
166 | /* set very specific priorities */ | ||
167 | gnutls_priority_set_direct(client, "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0", NULL); | ||
168 | gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred); | ||
169 | gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, c_certcred); | ||
170 | gnutls_server_name_set(client, GNUTLS_NAME_DNS, "www.verisign.com", strlen("www.verisign.com")); | ||
171 | |||
172 | |||
173 | /* connect to the peer | ||
174 | */ | ||
175 | sd = tcp_connect (); | ||
176 | |||
177 | /* associate gnutls with socket */ | ||
178 | gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t) sd); | ||
179 | /* add a callback for data being available for send/receive on socket */ | ||
180 | if (!ecore_main_fd_handler_add(sd, ECORE_FD_READ | ECORE_FD_WRITE, (Ecore_Fd_Cb)_process_data, client, NULL, NULL)) | ||
181 | { | ||
182 | print("could not create fd handler!"); | ||
183 | exit(1); | ||
184 | } | ||
185 | /* begin main loop */ | ||
186 | ecore_main_loop_begin(); | ||
187 | |||
188 | gnutls_bye (client, GNUTLS_SHUT_RDWR); | ||
189 | |||
190 | gnutls_deinit (client); | ||
191 | |||
192 | tcp_close (sd); | ||
193 | |||
194 | return 0; | ||
195 | } | ||