Blame


1 f224a3fe 2021-08-24 xhr /*
2 f224a3fe 2021-08-24 xhr * Copyright (c) 2021 Matthias Schmidt <xhr@giessen.ccc.de>
3 f224a3fe 2021-08-24 xhr *
4 f224a3fe 2021-08-24 xhr * Permission to use, copy, modify, and distribute this software for any
5 f224a3fe 2021-08-24 xhr * purpose with or without fee is hereby granted, provided that the above
6 f224a3fe 2021-08-24 xhr * copyright notice and this permission notice appear in all copies.
7 f224a3fe 2021-08-24 xhr *
8 f224a3fe 2021-08-24 xhr * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 f224a3fe 2021-08-24 xhr * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 f224a3fe 2021-08-24 xhr * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 f224a3fe 2021-08-24 xhr * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 f224a3fe 2021-08-24 xhr * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 f224a3fe 2021-08-24 xhr * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 f224a3fe 2021-08-24 xhr * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 f224a3fe 2021-08-24 xhr */
16 f224a3fe 2021-08-24 xhr
17 f224a3fe 2021-08-24 xhr #include <sys/socket.h>
18 f224a3fe 2021-08-24 xhr #include <sys/stat.h>
19 f224a3fe 2021-08-24 xhr
20 f224a3fe 2021-08-24 xhr #include <err.h>
21 f224a3fe 2021-08-24 xhr #include <errno.h>
22 f224a3fe 2021-08-24 xhr #include <fcntl.h>
23 f224a3fe 2021-08-24 xhr #include <stdio.h>
24 f224a3fe 2021-08-24 xhr #include <string.h>
25 f224a3fe 2021-08-24 xhr #include <unistd.h>
26 f224a3fe 2021-08-24 xhr
27 f224a3fe 2021-08-24 xhr #include "log.h"
28 f224a3fe 2021-08-24 xhr #include "twind.h"
29 f224a3fe 2021-08-24 xhr
30 f224a3fe 2021-08-24 xhr static void
31 f224a3fe 2021-08-24 xhr generate_meta(int status_code, char *meta_response_string, const char *mime)
32 f224a3fe 2021-08-24 xhr {
33 f224a3fe 2021-08-24 xhr switch(status_code) {
34 f224a3fe 2021-08-24 xhr case STATUS_INPUT:
35 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Present input\r\n", status_code);
36 f224a3fe 2021-08-24 xhr break;
37 f224a3fe 2021-08-24 xhr case STATUS_SENSITIVE_INPUT:
38 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Present sensitive input\r\n",
39 f224a3fe 2021-08-24 xhr status_code);
40 f224a3fe 2021-08-24 xhr break;
41 f224a3fe 2021-08-24 xhr case STATUS_SUCCESS:
42 f224a3fe 2021-08-24 xhr if (mime == NULL)
43 f224a3fe 2021-08-24 xhr /* Could not deducte mime type, so send text/gemini as default */
44 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d text/gemini\r\n", status_code);
45 f224a3fe 2021-08-24 xhr else
46 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d %s\r\n", status_code, mime);
47 f224a3fe 2021-08-24 xhr break;
48 f224a3fe 2021-08-24 xhr case STATUS_REDIRECT_TEMP:
49 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Temporary redirect\r\n",
50 f224a3fe 2021-08-24 xhr status_code);
51 f224a3fe 2021-08-24 xhr break;
52 f224a3fe 2021-08-24 xhr case STATUS_REDIRECT_PERM:
53 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Permanent redirect\r\n",
54 f224a3fe 2021-08-24 xhr status_code);
55 f224a3fe 2021-08-24 xhr break;
56 f224a3fe 2021-08-24 xhr case STATUS_TEMP_UNAVAILABLE:
57 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Temporary failure\r\n",
58 f224a3fe 2021-08-24 xhr status_code);
59 f224a3fe 2021-08-24 xhr break;
60 f224a3fe 2021-08-24 xhr case STATUS_SERVER_UNAVAILABLE:
61 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Server unavailable\r\n",
62 f224a3fe 2021-08-24 xhr status_code);
63 f224a3fe 2021-08-24 xhr break;
64 f224a3fe 2021-08-24 xhr case STATUS_CGI_ERROR:
65 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d CGI Error\r\n", status_code);
66 f224a3fe 2021-08-24 xhr break;
67 f224a3fe 2021-08-24 xhr case STATUS_PROXY_ERROR:
68 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Proxy error\r\n", status_code);
69 f224a3fe 2021-08-24 xhr break;
70 f224a3fe 2021-08-24 xhr case STATUS_SLOW_DOWN:
71 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Slow down\r\n", status_code);
72 f224a3fe 2021-08-24 xhr break;
73 f224a3fe 2021-08-24 xhr case STATUS_PERM_FAILURE:
74 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Permanent failure\r\n", status_code);
75 f224a3fe 2021-08-24 xhr break;
76 f224a3fe 2021-08-24 xhr case STATUS_NOT_FOUND:
77 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Resource not found\r\n",
78 f224a3fe 2021-08-24 xhr status_code);
79 f224a3fe 2021-08-24 xhr break;
80 f224a3fe 2021-08-24 xhr case STATUS_GONE:
81 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Resource is gone\r\n", status_code);
82 f224a3fe 2021-08-24 xhr break;
83 f224a3fe 2021-08-24 xhr case STATUS_PROXY_REQUEST_REFUSED:
84 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Proxy request refused\r\n",
85 f224a3fe 2021-08-24 xhr status_code);
86 f224a3fe 2021-08-24 xhr break;
87 f224a3fe 2021-08-24 xhr case STATUS_BAD_REQUEST:
88 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Bad Request\r\n", status_code);
89 f224a3fe 2021-08-24 xhr break;
90 f224a3fe 2021-08-24 xhr case STATUS_CLIENT_CERT_REQUIRED:
91 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Client Certificate Required\r\n",
92 f224a3fe 2021-08-24 xhr status_code);
93 f224a3fe 2021-08-24 xhr break;
94 f224a3fe 2021-08-24 xhr case STATUS_CERT_NOT_AUTHORIZED:
95 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Certificate not authorized\r\n",
96 f224a3fe 2021-08-24 xhr status_code);
97 f224a3fe 2021-08-24 xhr break;
98 f224a3fe 2021-08-24 xhr case STATUS_CERT_NOT_VALID:
99 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Certificate not valid\r\n",
100 f224a3fe 2021-08-24 xhr status_code);
101 f224a3fe 2021-08-24 xhr break;
102 f224a3fe 2021-08-24 xhr default:
103 f224a3fe 2021-08-24 xhr snprintf(meta_response_string, 1024, "%d Unkown status code\r\n",
104 f224a3fe 2021-08-24 xhr status_code);
105 f224a3fe 2021-08-24 xhr break;
106 f224a3fe 2021-08-24 xhr }
107 f224a3fe 2021-08-24 xhr }
108 f224a3fe 2021-08-24 xhr
109 f224a3fe 2021-08-24 xhr int
110 f224a3fe 2021-08-24 xhr send_non_success_response(SSL *ssl_peer, int status_code)
111 f224a3fe 2021-08-24 xhr {
112 f224a3fe 2021-08-24 xhr char meta[1024];
113 f224a3fe 2021-08-24 xhr
114 f224a3fe 2021-08-24 xhr memset(meta, 0, sizeof(meta));
115 f224a3fe 2021-08-24 xhr
116 f224a3fe 2021-08-24 xhr generate_meta(status_code, meta, NULL);
117 f224a3fe 2021-08-24 xhr
118 f224a3fe 2021-08-24 xhr log_debug("Send non success response to client: %d", status_code);
119 f224a3fe 2021-08-24 xhr
120 f224a3fe 2021-08-24 xhr if (SSL_write(ssl_peer, meta, strlen(meta)) <= 0) {
121 f224a3fe 2021-08-24 xhr log_warn("Could not send response to client");
122 f224a3fe 2021-08-24 xhr return -1;
123 f224a3fe 2021-08-24 xhr }
124 f224a3fe 2021-08-24 xhr
125 f224a3fe 2021-08-24 xhr return 0;
126 f224a3fe 2021-08-24 xhr }
127 f224a3fe 2021-08-24 xhr
128 f224a3fe 2021-08-24 xhr int
129 f224a3fe 2021-08-24 xhr send_response(SSL *ssl_peer, int status_code, const char *gemini_file_path,
130 f224a3fe 2021-08-24 xhr const char *mime)
131 f224a3fe 2021-08-24 xhr {
132 f224a3fe 2021-08-24 xhr char meta[1024];
133 f224a3fe 2021-08-24 xhr char buffer[1024];
134 f224a3fe 2021-08-24 xhr int fd = -1, len;
135 f224a3fe 2021-08-24 xhr
136 f224a3fe 2021-08-24 xhr // <STATUS><SPACE><META><CR><LF>
137 f224a3fe 2021-08-24 xhr
138 f224a3fe 2021-08-24 xhr memset(meta, 0, sizeof(meta));
139 f224a3fe 2021-08-24 xhr memset(buffer, 0, sizeof(buffer));
140 f224a3fe 2021-08-24 xhr
141 f224a3fe 2021-08-24 xhr generate_meta(status_code, meta, mime);
142 f224a3fe 2021-08-24 xhr
143 f224a3fe 2021-08-24 xhr if (SSL_write(ssl_peer, meta, strlen(meta)) <= 0) {
144 f224a3fe 2021-08-24 xhr log_warn("Could not send response to client");
145 f224a3fe 2021-08-24 xhr return -1;
146 f224a3fe 2021-08-24 xhr }
147 f224a3fe 2021-08-24 xhr
148 f224a3fe 2021-08-24 xhr /* Close connection and do not send a response if status code is not
149 f224a3fe 2021-08-24 xhr * a SUCCESS code
150 f224a3fe 2021-08-24 xhr */
151 f224a3fe 2021-08-24 xhr if (status_code < 30 && status_code >= 20) {
152 f224a3fe 2021-08-24 xhr fd = open(gemini_file_path, O_RDONLY);
153 f224a3fe 2021-08-24 xhr if (fd == -1) {
154 f224a3fe 2021-08-24 xhr log_warn("Cannot open requested file");
155 f224a3fe 2021-08-24 xhr goto out;
156 f224a3fe 2021-08-24 xhr }
157 f224a3fe 2021-08-24 xhr
158 f224a3fe 2021-08-24 xhr while ((len = read(fd, buffer, sizeof(buffer)-1)) > 0) {
159 f224a3fe 2021-08-24 xhr if (SSL_write(ssl_peer, buffer, len) <= 0) {
160 f224a3fe 2021-08-24 xhr log_warn("Could not send response to client");
161 f224a3fe 2021-08-24 xhr return -1;
162 f224a3fe 2021-08-24 xhr }
163 f224a3fe 2021-08-24 xhr }
164 f224a3fe 2021-08-24 xhr }
165 f224a3fe 2021-08-24 xhr
166 f224a3fe 2021-08-24 xhr out:
167 f224a3fe 2021-08-24 xhr close(fd);
168 f224a3fe 2021-08-24 xhr
169 f224a3fe 2021-08-24 xhr return 0;
170 f224a3fe 2021-08-24 xhr }
171 f224a3fe 2021-08-24 xhr
172 f224a3fe 2021-08-24 xhr int
173 f224a3fe 2021-08-24 xhr check_gemini_file(const char *gemini_file_path)
174 f224a3fe 2021-08-24 xhr {
175 f224a3fe 2021-08-24 xhr struct stat sb;
176 f224a3fe 2021-08-24 xhr
177 f224a3fe 2021-08-24 xhr if (stat(gemini_file_path, &sb) == -1) {
178 f224a3fe 2021-08-24 xhr log_warn("Cannot open requested file");
179 f224a3fe 2021-08-24 xhr return -1;
180 f224a3fe 2021-08-24 xhr }
181 f224a3fe 2021-08-24 xhr
182 f224a3fe 2021-08-24 xhr if ((sb.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
183 f224a3fe 2021-08-24 xhr log_warn("Cannot read requested file");
184 f224a3fe 2021-08-24 xhr return -1;
185 f224a3fe 2021-08-24 xhr }
186 f224a3fe 2021-08-24 xhr
187 f224a3fe 2021-08-24 xhr if ((sb.st_mode & S_IFMT) == S_IFDIR)
188 f224a3fe 2021-08-24 xhr return 1;
189 f224a3fe 2021-08-24 xhr
190 f224a3fe 2021-08-24 xhr return 0;
191 f224a3fe 2021-08-24 xhr }