Line data Source code
1 : /*
2 : START OF LICENSE STUB
3 : DeDOS: Declarative Dispersion-Oriented Software
4 : Copyright (C) 2017 University of Pennsylvania, Georgetown University
5 :
6 : This program is free software: you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : END OF LICENSE STUB
19 : */
20 : #include "webserver/read_msu.h"
21 : #include "webserver/http_msu.h"
22 : #include "webserver/sslops.h"
23 : #include "socket_msu.h"
24 : #include "webserver/connection-handler.h"
25 : #include "routing_strategies.h"
26 : #include "logging.h"
27 : #include "msu_state.h"
28 : #include "local_msu.h"
29 : #include "msu_message.h"
30 : #include "routing.h"
31 : #include "local_files.h"
32 : #include "msu_calls.h"
33 : #include "unused_def.h"
34 :
35 : #include <signal.h>
36 :
37 : struct ws_read_state {
38 : int use_ssl;
39 : };
40 :
41 296 : static int handle_read(struct read_state *read_state,
42 : struct ws_read_state *msu_state,
43 : struct local_msu *self,
44 : struct msu_msg *msg) {
45 296 : log(LOG_WEBSERVER_READ, "Attempting read from %p", read_state);
46 296 : int rtn = read_request(read_state);
47 296 : if (rtn & (WS_INCOMPLETE_WRITE | WS_INCOMPLETE_READ)) {
48 149 : read_state->conn.status = CON_READING;
49 149 : log(LOG_WEBSERVER_READ, "Read incomplete. Re-enabling (fd: %d)", read_state->conn.fd);
50 149 : msu_monitor_fd(read_state->conn.fd, RTN_TO_EVT(rtn), self, &msg->hdr);
51 149 : free(msg->data);
52 149 : return 0;
53 147 : } else if (rtn & WS_ERROR) {
54 1 : struct connection conn = read_state->conn;
55 1 : msu_free_state(self, &msg->hdr.key);
56 1 : log(LOG_WEBSERVER_READ, "Error when reading from socket!");
57 1 : msu_error(self, &msg->hdr, 1);
58 1 : log(LOG_WEBSERVER_READ, "Error when reading from socket!");
59 1 : msu_remove_fd_monitor(conn.fd);
60 1 : log(LOG_WEBSERVER_READ, "Error when reading from socket!");
61 1 : close_connection(&conn);
62 1 : return 0;
63 : } else {
64 146 : log(LOG_WEBSERVER_READ, "Read %s", read_state->req);
65 : }
66 146 : struct read_state *out = malloc(sizeof(*out));
67 146 : memcpy(out, read_state, sizeof(*read_state));
68 146 : msu_free_state(self, &msg->hdr.key);
69 146 : free(msg->data);
70 146 : call_msu_type(self, &WEBSERVER_HTTP_MSU_TYPE, &msg->hdr, sizeof(*out), out);
71 146 : return 0;
72 : }
73 :
74 296 : static int handle_accept(struct read_state *read_state,
75 : struct ws_read_state *msu_state,
76 : struct local_msu *self,
77 : struct msu_msg *msg) {
78 296 : int rtn = accept_connection(&read_state->conn, msu_state->use_ssl);
79 296 : if (rtn & WS_COMPLETE) {
80 148 : rtn = handle_read(read_state, msu_state, self, msg);
81 148 : return rtn;
82 148 : } else if (rtn & WS_ERROR) {
83 0 : msu_error(self, NULL, 0);
84 0 : msu_remove_fd_monitor(read_state->conn.fd);
85 0 : close_connection(&read_state->conn);
86 0 : msu_free_state(self, &msg->hdr.key);
87 0 : free(msg->data);
88 0 : return -1;
89 : } else {
90 148 : read_state->conn.status = CON_SSL_CONNECTING;
91 148 : return msu_monitor_fd(read_state->conn.fd, RTN_TO_EVT(rtn), self, &msg->hdr);
92 : }
93 : }
94 :
95 444 : static int read_http_request(struct local_msu *self,
96 : struct msu_msg *msg) {
97 444 : struct ws_read_state *msu_state = self->msu_state;
98 :
99 : struct connection conn_in;
100 444 : int sender_type_id = msu_msg_sender_type(&msg->hdr.provinance);
101 444 : switch (sender_type_id) {
102 : case SOCKET_MSU_TYPE_ID:;
103 441 : struct socket_msg *msg_in = msg->data;
104 441 : init_connection(&conn_in, msg_in->fd);
105 441 : break;
106 : case WEBSERVER_HTTP_MSU_TYPE_ID:
107 3 : log(LOG_WEBSERVER_READ, "Got back read msg %u", msg->hdr.key.id);
108 3 : conn_in = *(struct connection*)msg->data;
109 3 : break;
110 : default:
111 0 : log_error("Unknown sender MSU type ID: %d", sender_type_id);
112 0 : return -1;
113 : }
114 :
115 444 : size_t size = -1;
116 444 : struct read_state *read_state = msu_get_state(self, &msg->hdr.key, &size);
117 444 : if (read_state == NULL) {
118 153 : read_state = msu_init_state(self, &msg->hdr.key, sizeof(*read_state));
119 153 : init_read_state(read_state, &conn_in);
120 : } else {
121 291 : log(LOG_WEBSERVER_READ, "Retrieved read ptr %p", read_state);
122 : }
123 444 : if (read_state->conn.fd != conn_in.fd) {
124 0 : log_error("Got non-matching FDs! state: %d vs input: %d", read_state->conn.fd, conn_in.fd);
125 0 : return -1;
126 : }
127 :
128 444 : switch (read_state->conn.status) {
129 : case NIL:
130 : case NO_CONNECTION:
131 : case CON_ACCEPTED:
132 : case CON_SSL_CONNECTING:
133 296 : return handle_accept(read_state, msu_state, self, msg);
134 : case CON_READING:
135 : // TODO: I think it may never get here...
136 148 : return handle_read(read_state, msu_state, self, msg);
137 : default:
138 0 : log_error("Received unknown packet status: %d", read_state->conn.status);
139 0 : return -1;
140 : }
141 : }
142 :
143 : #define SSL_INIT_CMD "SSL"
144 :
145 41 : static int ws_read_init(struct local_msu *self, struct msu_init_data *data) {
146 41 : struct ws_read_state *ws_state = malloc(sizeof(*ws_state));
147 :
148 41 : char *init_cmd = data->init_data;
149 :
150 41 : if (init_cmd == NULL) {
151 0 : log_info("Initializing NON-SSL webserver-reading MSU");
152 0 : ws_state->use_ssl = 0;
153 : }
154 41 : if (strncasecmp(init_cmd, SSL_INIT_CMD, sizeof(SSL_INIT_CMD)) == 0) {
155 13 : log_info("Initializing SSL webserver-reading MSU");
156 13 : ws_state->use_ssl = 1;
157 : } else {
158 28 : log_info("Initializing SSL webserver-reading MSU anyway");
159 28 : ws_state->use_ssl = 1;
160 : }
161 :
162 41 : self->msu_state = (void*)ws_state;
163 41 : return 0;
164 : }
165 :
166 36 : static void ws_read_destroy(struct local_msu *self) {
167 36 : free(self->msu_state);
168 36 : }
169 :
170 :
171 40 : static int init_ssl_ctx(struct msu_type UNUSED *type) {
172 40 : init_ssl_locks();
173 40 : if (init_ssl_context() != 0) {
174 0 : log_critical("Error intiializing SSL context");
175 0 : return -1;
176 : }
177 :
178 : char pem_file[256];
179 40 : get_local_file(pem_file, "mycert.pem");
180 40 : if (load_ssl_certificate(pem_file, pem_file) != 0) {
181 0 : log_error("Error loading SSL cert %s", pem_file);
182 0 : return -1;
183 : }
184 :
185 40 : signal(SIGPIPE, SIG_IGN);
186 :
187 40 : return 0;
188 : }
189 :
190 35 : static void destroy_ssl_ctx(struct msu_type UNUSED *type) {
191 35 : kill_ssl_locks();
192 35 : }
193 :
194 : struct msu_type WEBSERVER_READ_MSU_TYPE = {
195 : .name = "Webserver_read_MSU",
196 : .id = WEBSERVER_READ_MSU_TYPE_ID,
197 : .init_type = init_ssl_ctx,
198 : .destroy_type = destroy_ssl_ctx,
199 : .init = ws_read_init,
200 : .destroy = ws_read_destroy,
201 : .route = route_to_origin_runtime,
202 : .receive = read_http_request
203 : };
|