| 1 | #include"main.h" |
|---|
| 2 | |
|---|
| 3 | #define MAX_NAME_LEN 256 |
|---|
| 4 | #define BUFFER 4*1024 |
|---|
| 5 | |
|---|
| 6 | void * handle(void * args) |
|---|
| 7 | { |
|---|
| 8 | char * getbuffer = calloc(MAX_NAME_LEN, sizeof(char)); |
|---|
| 9 | char * buffer = calloc(MAX_NAME_LEN*2, sizeof(char)); |
|---|
| 10 | char * netbuffer = calloc(BUFFER, sizeof(char)); |
|---|
| 11 | size_t size = 0; |
|---|
| 12 | size_t offset = 0; |
|---|
| 13 | int mode = 0; // 1 is connection established |
|---|
| 14 | struct service * service = NULL; |
|---|
| 15 | struct service * listservice = NULL; |
|---|
| 16 | int i = 0; |
|---|
| 17 | int outsock = 0; |
|---|
| 18 | int waiting = 0; |
|---|
| 19 | char * response; |
|---|
| 20 | struct epoll_event ev, *events; //For epoll() |
|---|
| 21 | int len; |
|---|
| 22 | char * check = calloc(BUFFER, sizeof(char)); |
|---|
| 23 | |
|---|
| 24 | struct session * s = calloc(1, sizeof(struct session)); |
|---|
| 25 | s->sock = (int) args; |
|---|
| 26 | s->ssl = NULL; // If this is set, we need to use SSL |
|---|
| 27 | s->contxt = NULL; |
|---|
| 28 | s->multiplex = 0; |
|---|
| 29 | s->multiplex_xtra = 0; |
|---|
| 30 | //s->header[16]; |
|---|
| 31 | s->ptr = (unsigned int *) &s->header; |
|---|
| 32 | s->user = NULL; |
|---|
| 33 | s->host = "main"; |
|---|
| 34 | |
|---|
| 35 | /* Epoll Initialization */ |
|---|
| 36 | int epfd = epoll_create(16); |
|---|
| 37 | events = calloc(16, sizeof(struct epoll_event)); |
|---|
| 38 | ev.events = EPOLLIN; |
|---|
| 39 | ev.data.fd = s->sock; |
|---|
| 40 | epoll_ctl(epfd, EPOLL_CTL_ADD, s->sock, &ev); |
|---|
| 41 | |
|---|
| 42 | while(1) |
|---|
| 43 | { |
|---|
| 44 | if(mode == 0) |
|---|
| 45 | { |
|---|
| 46 | incoming: |
|---|
| 47 | if(!s->ssl) //TODO: re-write everything here to use gettalk() |
|---|
| 48 | { |
|---|
| 49 | if(!s->multiplex) |
|---|
| 50 | size = read(s->sock, getbuffer, MAX_NAME_LEN); |
|---|
| 51 | else |
|---|
| 52 | { |
|---|
| 53 | if(len > MAX_NAME_LEN) |
|---|
| 54 | { |
|---|
| 55 | size = read(s->sock, getbuffer, MAX_NAME_LEN); |
|---|
| 56 | read(s->sock, netbuffer, len - MAX_NAME_LEN); //TODO: check overflow |
|---|
| 57 | } |
|---|
| 58 | size = read(s->sock, getbuffer, len); |
|---|
| 59 | } |
|---|
| 60 | } |
|---|
| 61 | else |
|---|
| 62 | { |
|---|
| 63 | if(!s->multiplex) |
|---|
| 64 | size = SSL_read(s->ssl, getbuffer, MAX_NAME_LEN); |
|---|
| 65 | else |
|---|
| 66 | { |
|---|
| 67 | if(len > MAX_NAME_LEN) |
|---|
| 68 | { |
|---|
| 69 | size = SSL_read(s->ssl, getbuffer, MAX_NAME_LEN); |
|---|
| 70 | SSL_read(s->ssl, netbuffer, len - MAX_NAME_LEN); //TODO: check overflow |
|---|
| 71 | } |
|---|
| 72 | size = SSL_read(s->ssl, getbuffer, len); |
|---|
| 73 | } |
|---|
| 74 | } |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | |
|---|
| 78 | if(size < 1) |
|---|
| 79 | { |
|---|
| 80 | kill: |
|---|
| 81 | if(s->ssl) |
|---|
| 82 | { |
|---|
| 83 | SSL_shutdown(s->ssl); |
|---|
| 84 | SSL_free(s->ssl); |
|---|
| 85 | SSL_CTX_free(s->contxt); |
|---|
| 86 | } |
|---|
| 87 | close(s->sock); |
|---|
| 88 | close(outsock); |
|---|
| 89 | close(epfd); |
|---|
| 90 | free(getbuffer); |
|---|
| 91 | free(buffer); |
|---|
| 92 | free(netbuffer); |
|---|
| 93 | free(events); |
|---|
| 94 | free(check); |
|---|
| 95 | printf("Client disconnected\n"); |
|---|
| 96 | return NULL; |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | printf("Parsing\n"); |
|---|
| 100 | service = parse(&offset, &size, getbuffer, buffer, s); |
|---|
| 101 | |
|---|
| 102 | if(service == (void *) -1) |
|---|
| 103 | continue; |
|---|
| 104 | |
|---|
| 105 | /* Catch all and access denied */ |
|---|
| 106 | if(service == NULL) |
|---|
| 107 | { |
|---|
| 108 | talkback(s, "- No Such Service\r\n"); |
|---|
| 109 | if(mode) |
|---|
| 110 | goto process; |
|---|
| 111 | else |
|---|
| 112 | continue; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | if(service->service_type == HELP_SERVICE || service->service_type == LIST_SERVICE) |
|---|
| 116 | { |
|---|
| 117 | i = 0; |
|---|
| 118 | response = calloc(BUFFER, sizeof(char)); |
|---|
| 119 | listservice = servicelist; |
|---|
| 120 | while(listservice) |
|---|
| 121 | { |
|---|
| 122 | if((listservice->service_type == HELP_SERVICE || listservice->service_type == LIST_SERVICE)) |
|---|
| 123 | { |
|---|
| 124 | listservice = listservice->next; |
|---|
| 125 | continue; |
|---|
| 126 | } |
|---|
| 127 | if((listservice->service_type == SSL_SERVICE && s->ssl) || (listservice->service_type == MULTIPLEX_SERVICE && s->multiplex)) |
|---|
| 128 | { |
|---|
| 129 | listservice = listservice->next; |
|---|
| 130 | continue; |
|---|
| 131 | } |
|---|
| 132 | if(listservice->restrict_user != NULL) |
|---|
| 133 | { |
|---|
| 134 | if(s->user == NULL || listservice->restrict_user == NULL) |
|---|
| 135 | { |
|---|
| 136 | listservice = listservice->next; |
|---|
| 137 | continue; |
|---|
| 138 | } |
|---|
| 139 | if(strcmp(s->user, listservice->restrict_user)) |
|---|
| 140 | { |
|---|
| 141 | listservice = listservice->next; |
|---|
| 142 | continue; |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | if(listservice->restrict_host != NULL) |
|---|
| 146 | { |
|---|
| 147 | if(s->host == NULL || listservice->restrict_host == NULL) |
|---|
| 148 | { |
|---|
| 149 | listservice = listservice->next; |
|---|
| 150 | continue; |
|---|
| 151 | } |
|---|
| 152 | if(strcmp(s->host, listservice->restrict_host)) |
|---|
| 153 | { |
|---|
| 154 | listservice = listservice->next; |
|---|
| 155 | continue; |
|---|
| 156 | } |
|---|
| 157 | } |
|---|
| 158 | i += strlen(listservice->name) + 2; |
|---|
| 159 | if(i > BUFFER) |
|---|
| 160 | response = realloc(response, i); |
|---|
| 161 | strcat(response+i-(strlen(listservice->name)+2), listservice->name); |
|---|
| 162 | response[i-1] = '\n'; |
|---|
| 163 | response[i-2] = '\r'; |
|---|
| 164 | listservice = listservice->next; |
|---|
| 165 | } |
|---|
| 166 | talkback_len(s, response, i); |
|---|
| 167 | free(response); |
|---|
| 168 | if(service->service_type == HELP_SERVICE) |
|---|
| 169 | goto kill; |
|---|
| 170 | if(mode) |
|---|
| 171 | goto process; |
|---|
| 172 | else |
|---|
| 173 | continue; |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | if(service->service_type == MULTIPLEX_SERVICE) |
|---|
| 177 | { |
|---|
| 178 | if(s->multiplex) |
|---|
| 179 | { |
|---|
| 180 | talkback(s, "- No Such Service\r\n"); |
|---|
| 181 | if(mode) |
|---|
| 182 | goto process; |
|---|
| 183 | else |
|---|
| 184 | continue; |
|---|
| 185 | } |
|---|
| 186 | talkback(s, "+ Success\r\n"); |
|---|
| 187 | s->multiplex = 1; |
|---|
| 188 | mode = 1; |
|---|
| 189 | /* Go into multiplex mode */ |
|---|
| 190 | send_header(s, 0, NEW_PLEX, 0); |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | if(service->service_type == SSL_SERVICE) |
|---|
| 194 | { |
|---|
| 195 | //TODO: OpenSSL is not re-entrant, care about that. |
|---|
| 196 | if(s->ssl) |
|---|
| 197 | { |
|---|
| 198 | talkback(s, "- No Such Service\r\n"); |
|---|
| 199 | if(mode) |
|---|
| 200 | goto process; |
|---|
| 201 | else |
|---|
| 202 | continue; |
|---|
| 203 | } |
|---|
| 204 | talkback(s, "+ Success\r\n"); |
|---|
| 205 | |
|---|
| 206 | s->contxt = SSL_CTX_new(SSLv23_server_method()); |
|---|
| 207 | if(!s->contxt) |
|---|
| 208 | printf("SSL_CTX_new failed\n"); |
|---|
| 209 | |
|---|
| 210 | i = SSL_CTX_use_RSAPrivateKey_file(s->contxt, "/home/djc/projects/fived/fived_key.pem", SSL_FILETYPE_PEM); |
|---|
| 211 | if(!i) |
|---|
| 212 | printf("RSA Key Load Failed\n"); |
|---|
| 213 | |
|---|
| 214 | i = SSL_CTX_use_certificate_file(s->contxt, "/home/djc/projects/fived/fived_cert.pem", SSL_FILETYPE_PEM); |
|---|
| 215 | if(!i) |
|---|
| 216 | printf("Cert Load Failed\n"); |
|---|
| 217 | |
|---|
| 218 | SSL_CTX_set_quiet_shutdown(s->contxt, 1); |
|---|
| 219 | |
|---|
| 220 | s->ssl = SSL_new(s->contxt); |
|---|
| 221 | if(!s->ssl) |
|---|
| 222 | printf("SSL_new failed\n"); |
|---|
| 223 | |
|---|
| 224 | i = SSL_set_fd(s->ssl, s->sock); |
|---|
| 225 | if(!i) |
|---|
| 226 | printf("SSL_set_fd failed\n"); |
|---|
| 227 | |
|---|
| 228 | SSL_set_accept_state(s->ssl); |
|---|
| 229 | i = SSL_accept(s->ssl); |
|---|
| 230 | if(i < 1) |
|---|
| 231 | { |
|---|
| 232 | printf("SSL_accept failed\n"); |
|---|
| 233 | switch(SSL_get_error(s->ssl, i)) |
|---|
| 234 | { |
|---|
| 235 | case SSL_ERROR_NONE: |
|---|
| 236 | printf("no error\n"); |
|---|
| 237 | break; |
|---|
| 238 | case SSL_ERROR_WANT_X509_LOOKUP: |
|---|
| 239 | printf("X509 error\n"); |
|---|
| 240 | break; |
|---|
| 241 | case SSL_ERROR_SSL: |
|---|
| 242 | printf("You did something wrong\n"); |
|---|
| 243 | break; |
|---|
| 244 | case SSL_ERROR_SYSCALL: |
|---|
| 245 | printf("Someone else did something wrong (syscall)\n"); |
|---|
| 246 | break; |
|---|
| 247 | default: |
|---|
| 248 | printf("Idunnolol\n"); |
|---|
| 249 | break; |
|---|
| 250 | } |
|---|
| 251 | } |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | /* Imagine the most minimalistic demo-driven auth service you could think of... this is a hair below that */ |
|---|
| 255 | if(service->service_type == AUTH_SERVICE) |
|---|
| 256 | { |
|---|
| 257 | talkback(s, "+ Success\r\nEnter Username: "); |
|---|
| 258 | gettalk(s, check, 0); // username (TODO: unsafe) |
|---|
| 259 | talkback(s, "Enter Password: "); |
|---|
| 260 | gettalk(s, check, 0); // password (TODO: unsafe) |
|---|
| 261 | if(!strncmp("demopass", check, 8)) |
|---|
| 262 | { |
|---|
| 263 | s->user = "demo"; |
|---|
| 264 | talkback(s, "Authentication as demo successful\r\n"); |
|---|
| 265 | } |
|---|
| 266 | else |
|---|
| 267 | { |
|---|
| 268 | talkback(s, "Authentication failed\r\n"); |
|---|
| 269 | } |
|---|
| 270 | } |
|---|
| 271 | |
|---|
| 272 | if(service->service_type == HOST_SERVICE) |
|---|
| 273 | { |
|---|
| 274 | talkback(s, "+ Success\r\nWhich VHOST? "); |
|---|
| 275 | gettalk(s, check, 0); // host (TODO: unsafe); |
|---|
| 276 | if(!strncmp(check, "toys", 4)) |
|---|
| 277 | { |
|---|
| 278 | s->host = "toys"; |
|---|
| 279 | talkback(s, "+ Success: Host changed to toys\r\n"); |
|---|
| 280 | } |
|---|
| 281 | else if(!strncmp(check, "main", 4)) |
|---|
| 282 | { |
|---|
| 283 | s->host = "main"; |
|---|
| 284 | talkback(s, "+ Success: Host changed to main\r\n"); |
|---|
| 285 | } |
|---|
| 286 | else |
|---|
| 287 | { |
|---|
| 288 | talkback(s, "- Invalid hostname\r\n"); |
|---|
| 289 | } |
|---|
| 290 | } |
|---|
| 291 | |
|---|
| 292 | if(service->service_type == CUSTOM_SERVICE) |
|---|
| 293 | { |
|---|
| 294 | // TODO: access control |
|---|
| 295 | outsock = socket(PF_INET6, SOCK_STREAM, 0); |
|---|
| 296 | error(outsock); |
|---|
| 297 | i = connect(outsock, (const struct sockaddr *) service->info, sizeof(struct sockaddr_in6)); |
|---|
| 298 | error(i); |
|---|
| 299 | |
|---|
| 300 | /* Add to epoll() */ |
|---|
| 301 | ev.data.fd = outsock; |
|---|
| 302 | i = epoll_ctl(epfd, EPOLL_CTL_ADD, outsock, &ev); |
|---|
| 303 | error(i); |
|---|
| 304 | printf("Adding fd %d to epoll\n", outsock); |
|---|
| 305 | |
|---|
| 306 | /* For multiplexing, or not */ |
|---|
| 307 | if(mode != 2) |
|---|
| 308 | mode = 1; |
|---|
| 309 | |
|---|
| 310 | talkback(s, "+ Success\r\n"); |
|---|
| 311 | |
|---|
| 312 | //TODO: Much more interesting things happen here during multiplexing |
|---|
| 313 | if(s->multiplex) |
|---|
| 314 | send_header(s, outsock, NEW_PLEX, 0); |
|---|
| 315 | } |
|---|
| 316 | |
|---|
| 317 | goto deny; //get rid of unused label warnings. |
|---|
| 318 | deny: |
|---|
| 319 | /* Catch all and access denied */ |
|---|
| 320 | if(service == NULL) |
|---|
| 321 | talkback(s, "- No Such Service\r\n"); |
|---|
| 322 | |
|---|
| 323 | process: |
|---|
| 324 | if(mode == 1) |
|---|
| 325 | { |
|---|
| 326 | len = 0; |
|---|
| 327 | while(1) |
|---|
| 328 | { |
|---|
| 329 | waiting = epoll_wait(epfd, events, 16, -1); |
|---|
| 330 | error(waiting); |
|---|
| 331 | for(i=0;i<waiting;i++) |
|---|
| 332 | { |
|---|
| 333 | if(s->multiplex) |
|---|
| 334 | { |
|---|
| 335 | //printf("fd %d has an event\n", events[i].data.fd); |
|---|
| 336 | if(events[i].data.fd != s->sock) |
|---|
| 337 | { |
|---|
| 338 | len = read(events[i].data.fd, netbuffer, BUFFER); |
|---|
| 339 | if(len < 1) |
|---|
| 340 | { |
|---|
| 341 | send_header(s, events[i].data.fd, DEL_PLEX, 0); |
|---|
| 342 | epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); |
|---|
| 343 | continue; |
|---|
| 344 | } |
|---|
| 345 | send_header(s, events[i].data.fd, 0, len); |
|---|
| 346 | if(!s->ssl) |
|---|
| 347 | write(s->sock, netbuffer, len); |
|---|
| 348 | else |
|---|
| 349 | SSL_write(s->ssl, netbuffer, len); |
|---|
| 350 | continue; |
|---|
| 351 | } |
|---|
| 352 | if(!s->ssl) |
|---|
| 353 | len = read(s->sock, &s->header, 16); |
|---|
| 354 | else |
|---|
| 355 | len = SSL_read(s->ssl, &s->header, 16); |
|---|
| 356 | //printf("%x | %x | %x | %x\n", ntohl(s->ptr[0]), ntohl(s->ptr[1]), ntohl(s->ptr[2]), ntohl(s->ptr[3])); |
|---|
| 357 | //if(len < 1) |
|---|
| 358 | if(len != 16) |
|---|
| 359 | goto kill; |
|---|
| 360 | s->multiplex_xtra = ntohl(s->ptr[3]); |
|---|
| 361 | if(ntohl(s->ptr[1]) == 0 && ntohl(s->ptr[3]) != 0) //They're talking to tcpmux |
|---|
| 362 | { |
|---|
| 363 | if(ntohl(s->ptr[2]) != 0) |
|---|
| 364 | printf("Client is sending flags about id 0, something is wrong\n"); |
|---|
| 365 | len = s->multiplex_xtra; |
|---|
| 366 | s->multiplex_xtra = 0; //TODO: revise this when you refactor the incoming module |
|---|
| 367 | goto incoming; |
|---|
| 368 | } |
|---|
| 369 | if(ntohl(s->ptr[2]) == DEL_PLEX) |
|---|
| 370 | { |
|---|
| 371 | close(ntohl(s->ptr[1])); //TODO: Yeah, we should actually have our own table and be verifying |
|---|
| 372 | continue; |
|---|
| 373 | } |
|---|
| 374 | while(s->multiplex_xtra != 0) |
|---|
| 375 | { |
|---|
| 376 | if(s->multiplex_xtra > BUFFER) |
|---|
| 377 | len = BUFFER; |
|---|
| 378 | else |
|---|
| 379 | len = s->multiplex_xtra; |
|---|
| 380 | if(!s->ssl) |
|---|
| 381 | len = read(s->sock, netbuffer, len); |
|---|
| 382 | else |
|---|
| 383 | len = SSL_read(s->ssl, netbuffer, len); |
|---|
| 384 | chk_error(write(ntohl(s->ptr[1]), netbuffer, len) != len); |
|---|
| 385 | //printf("Wrote %d bytes to fd %d\n", len, ntohl(s->ptr[1])); |
|---|
| 386 | s->multiplex_xtra -= len; |
|---|
| 387 | } |
|---|
| 388 | continue; |
|---|
| 389 | } |
|---|
| 390 | if(!s->ssl || events[i].data.fd != s->sock) |
|---|
| 391 | len = read(events[i].data.fd, netbuffer, BUFFER); |
|---|
| 392 | else |
|---|
| 393 | len = SSL_read(s->ssl, netbuffer, BUFFER); |
|---|
| 394 | if(len < 1) |
|---|
| 395 | goto kill; |
|---|
| 396 | if(events[i].data.fd == s->sock) |
|---|
| 397 | write(outsock, netbuffer, len); |
|---|
| 398 | else |
|---|
| 399 | { |
|---|
| 400 | if(!s->ssl) |
|---|
| 401 | write(s->sock, netbuffer, len); |
|---|
| 402 | else |
|---|
| 403 | SSL_write(s->ssl, netbuffer, len); |
|---|
| 404 | } |
|---|
| 405 | } |
|---|
| 406 | } |
|---|
| 407 | } |
|---|
| 408 | } |
|---|
| 409 | |
|---|
| 410 | err: |
|---|
| 411 | perror("Error"); |
|---|
| 412 | |
|---|
| 413 | return NULL; |
|---|
| 414 | } |
|---|
| 415 | |
|---|
| 416 | struct service * parse(size_t * offset, size_t * size, char * getbuffer, char * buffer, struct session * s) |
|---|
| 417 | { |
|---|
| 418 | unsigned int i = 0; |
|---|
| 419 | char * name; |
|---|
| 420 | memcpy(buffer+(*offset), getbuffer, *size); |
|---|
| 421 | *size += *offset; |
|---|
| 422 | for(i = 0; i < *size; ++i) |
|---|
| 423 | { |
|---|
| 424 | if(buffer[i] == '\r' || buffer[i] == '\n') |
|---|
| 425 | break; |
|---|
| 426 | } |
|---|
| 427 | |
|---|
| 428 | /* So there's no newline in the entire message */ |
|---|
| 429 | if(i == *size) |
|---|
| 430 | { |
|---|
| 431 | *offset += *size - *offset; |
|---|
| 432 | if(*offset > MAX_NAME_LEN) |
|---|
| 433 | *offset = 0; |
|---|
| 434 | return (struct service *) -1; //Presumably not a value a pointer can have. |
|---|
| 435 | } |
|---|
| 436 | |
|---|
| 437 | /* There's a valid name of some sort */ |
|---|
| 438 | name = calloc(i+1, sizeof(char)); |
|---|
| 439 | memcpy(name, buffer, i+1); |
|---|
| 440 | name[i] = '\0'; //Replace \n or \r with null terminator |
|---|
| 441 | if(i == *size - 1 || (i == *size - 2 && buffer[i+1] == '\n')) |
|---|
| 442 | *offset = 0; |
|---|
| 443 | else //There is remaining data left to parse. |
|---|
| 444 | { |
|---|
| 445 | if(i != *size-1) |
|---|
| 446 | { |
|---|
| 447 | if(buffer[i] == '\r' && buffer[i+1] == '\n') |
|---|
| 448 | { |
|---|
| 449 | *offset = i+2; |
|---|
| 450 | memmove(buffer, buffer + i+2, *size - i+2); |
|---|
| 451 | } |
|---|
| 452 | else |
|---|
| 453 | { |
|---|
| 454 | *offset = i+1; |
|---|
| 455 | memmove(buffer, buffer + i+1, *size - i+1); |
|---|
| 456 | } |
|---|
| 457 | } |
|---|
| 458 | else |
|---|
| 459 | { |
|---|
| 460 | *offset = i+1; |
|---|
| 461 | memmove(buffer, buffer + i+1, *size - i+1); |
|---|
| 462 | } |
|---|
| 463 | } |
|---|
| 464 | |
|---|
| 465 | //TODO, make syslog "attempt to request service x" |
|---|
| 466 | printf("Service name is %s\n", name); |
|---|
| 467 | |
|---|
| 468 | struct service * current = servicelist; |
|---|
| 469 | while(current) |
|---|
| 470 | { |
|---|
| 471 | if(current ->restrict_user != NULL) |
|---|
| 472 | { |
|---|
| 473 | if(s->user == NULL || current->restrict_user == NULL) |
|---|
| 474 | { |
|---|
| 475 | current = current->next; |
|---|
| 476 | continue; |
|---|
| 477 | } |
|---|
| 478 | if(strcmp(s->user, current->restrict_user)) |
|---|
| 479 | { |
|---|
| 480 | current = current->next; |
|---|
| 481 | continue; |
|---|
| 482 | } |
|---|
| 483 | } |
|---|
| 484 | if(current->restrict_host != NULL) |
|---|
| 485 | { |
|---|
| 486 | if(s->host == NULL || current->restrict_host == NULL) |
|---|
| 487 | { |
|---|
| 488 | current = current->next; |
|---|
| 489 | continue; |
|---|
| 490 | } |
|---|
| 491 | if(strcmp(s->host, current->restrict_host)) |
|---|
| 492 | { |
|---|
| 493 | current = current->next; |
|---|
| 494 | continue; |
|---|
| 495 | } |
|---|
| 496 | } |
|---|
| 497 | if(strncmp(current->name,name,MAX_NAME_LEN) == 0) |
|---|
| 498 | return current; |
|---|
| 499 | current = current->next; |
|---|
| 500 | } |
|---|
| 501 | |
|---|
| 502 | return NULL; |
|---|
| 503 | } |
|---|
| 504 | |
|---|
| 505 | void send_header(struct session * s, int id, int flags, int len) |
|---|
| 506 | { |
|---|
| 507 | //printf("Sending to id %d len %d with flags %d\n", id, len, flags); |
|---|
| 508 | char header[16]; |
|---|
| 509 | int * ptr = (int *) &header; |
|---|
| 510 | ptr[0] = htonl(0); //Version 0 |
|---|
| 511 | ptr[1] = htonl(id); //Id |
|---|
| 512 | ptr[2] = htonl(flags); //Flags (1 for new, 2 for del, 0 for normal) Rest reserved. |
|---|
| 513 | ptr[3] = htonl(len); //Next header |
|---|
| 514 | if(s->ssl) |
|---|
| 515 | SSL_write(s->ssl, &header, 16); |
|---|
| 516 | else |
|---|
| 517 | write(s->sock, &header, 16); |
|---|
| 518 | } |
|---|
| 519 | |
|---|
| 520 | void talkback_len(struct session * s, char * msg, int length) |
|---|
| 521 | { |
|---|
| 522 | if(s->multiplex) |
|---|
| 523 | send_header(s, 0, 0, length); |
|---|
| 524 | if(!s->ssl) |
|---|
| 525 | write(s->sock, msg, length); |
|---|
| 526 | else |
|---|
| 527 | SSL_write(s->ssl, msg, length); |
|---|
| 528 | } |
|---|
| 529 | |
|---|
| 530 | void talkback(struct session * s, char * msg) |
|---|
| 531 | { |
|---|
| 532 | talkback_len(s, msg, strlen(msg)); |
|---|
| 533 | } |
|---|
| 534 | |
|---|
| 535 | int gettalk(struct session * s, char * buffer, int length) |
|---|
| 536 | { |
|---|
| 537 | int len = 0; |
|---|
| 538 | if(length == 0 || length > BUFFER) |
|---|
| 539 | len = BUFFER; |
|---|
| 540 | else |
|---|
| 541 | len = length; |
|---|
| 542 | |
|---|
| 543 | if(s->multiplex && !s->multiplex_xtra) |
|---|
| 544 | { |
|---|
| 545 | if(!s->ssl) |
|---|
| 546 | { |
|---|
| 547 | chk_error(read(s->sock, &s->header, 16) != 16); |
|---|
| 548 | } |
|---|
| 549 | else |
|---|
| 550 | { |
|---|
| 551 | chk_error(SSL_read(s->ssl, &s->header, 16) != 16); |
|---|
| 552 | } |
|---|
| 553 | s->multiplex_xtra = ntohl(s->ptr[3]); |
|---|
| 554 | if(s->multiplex_xtra <= len) |
|---|
| 555 | { |
|---|
| 556 | len = s->multiplex_xtra; |
|---|
| 557 | s->multiplex_xtra = 0; |
|---|
| 558 | } |
|---|
| 559 | else |
|---|
| 560 | s->multiplex_xtra = s->multiplex_xtra - len; |
|---|
| 561 | } |
|---|
| 562 | if(s->ssl) |
|---|
| 563 | return SSL_read(s->ssl, buffer, len); |
|---|
| 564 | else |
|---|
| 565 | return read(s->sock, buffer, len); |
|---|
| 566 | |
|---|
| 567 | err: |
|---|
| 568 | printf("Failed get multiplexing header"); |
|---|
| 569 | return -1; |
|---|
| 570 | } |
|---|