1 /* 2 * Copyright (c) 1998-2002, 2005 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifdef FTP_SERVER 35 #include "ftpd_locl.h" 36 #else 37 #include "ftp_locl.h" 38 #endif 39 40 RCSID("$Id$"); 41 42 static enum protection_level command_prot; 43 static enum protection_level data_prot; 44 static size_t buffer_size; 45 46 struct buffer { 47 void *data; 48 size_t size; 49 size_t index; 50 int eof_flag; 51 }; 52 53 static struct buffer in_buffer, out_buffer; 54 int sec_complete; 55 56 static struct { 57 enum protection_level level; 58 const char *name; 59 } level_names[] = { 60 { prot_clear, "clear" }, 61 { prot_safe, "safe" }, 62 { prot_confidential, "confidential" }, 63 { prot_private, "private" } 64 }; 65 66 static const char * 67 level_to_name(enum protection_level level) 68 { 69 int i; 70 for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) 71 if(level_names[i].level == level) 72 return level_names[i].name; 73 return "unknown"; 74 } 75 76 #ifndef FTP_SERVER /* not used in server */ 77 static enum protection_level 78 name_to_level(const char *name) 79 { 80 int i; 81 for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++) 82 if(!strncasecmp(level_names[i].name, name, strlen(name))) 83 return level_names[i].level; 84 return prot_invalid; 85 } 86 #endif 87 88 #ifdef FTP_SERVER 89 90 static struct sec_server_mech *mechs[] = { 91 #ifdef KRB5 92 &gss_server_mech, 93 #endif 94 NULL 95 }; 96 97 static struct sec_server_mech *mech; 98 99 #else 100 101 static struct sec_client_mech *mechs[] = { 102 #ifdef KRB5 103 &gss_client_mech, 104 #endif 105 NULL 106 }; 107 108 static struct sec_client_mech *mech; 109 110 #endif 111 112 static void *app_data; 113 114 int 115 sec_getc(FILE *F) 116 { 117 if(sec_complete && data_prot) { 118 char c; 119 if(sec_read(fileno(F), &c, 1) <= 0) 120 return EOF; 121 return c; 122 } else 123 return getc(F); 124 } 125 126 static int 127 block_read(int fd, void *buf, size_t len) 128 { 129 unsigned char *p = buf; 130 int b; 131 while(len) { 132 b = read(fd, p, len); 133 if (b == 0) 134 return 0; 135 else if (b < 0) 136 return -1; 137 len -= b; 138 p += b; 139 } 140 return p - (unsigned char*)buf; 141 } 142 143 static int 144 block_write(int fd, void *buf, size_t len) 145 { 146 unsigned char *p = buf; 147 int b; 148 while(len) { 149 b = write(fd, p, len); 150 if(b < 0) 151 return -1; 152 len -= b; 153 p += b; 154 } 155 return p - (unsigned char*)buf; 156 } 157 158 static int 159 sec_get_data(int fd, struct buffer *buf, int level) 160 { 161 int len; 162 int b; 163 void *tmp; 164 165 b = block_read(fd, &len, sizeof(len)); 166 if (b == 0) 167 return 0; 168 else if (b < 0) 169 return -1; 170 len = ntohl(len); 171 tmp = realloc(buf->data, len); 172 if (tmp == NULL) 173 return -1; 174 buf->data = tmp; 175 b = block_read(fd, buf->data, len); 176 if (b == 0) 177 return 0; 178 else if (b < 0) 179 return -1; 180 buf->size = (*mech->decode)(app_data, buf->data, len, data_prot); 181 buf->index = 0; 182 return 0; 183 } 184 185 static size_t 186 buffer_read(struct buffer *buf, void *dataptr, size_t len) 187 { 188 len = min(len, buf->size - buf->index); 189 memcpy(dataptr, (char*)buf->data + buf->index, len); 190 buf->index += len; 191 return len; 192 } 193 194 static size_t 195 buffer_write(struct buffer *buf, void *dataptr, size_t len) 196 { 197 if(buf->index + len > buf->size) { 198 void *tmp; 199 if(buf->data == NULL) 200 tmp = malloc(1024); 201 else 202 tmp = realloc(buf->data, buf->index + len); 203 if(tmp == NULL) 204 return -1; 205 buf->data = tmp; 206 buf->size = buf->index + len; 207 } 208 memcpy((char*)buf->data + buf->index, dataptr, len); 209 buf->index += len; 210 return len; 211 } 212 213 int 214 sec_read(int fd, void *dataptr, int length) 215 { 216 size_t len; 217 int rx = 0; 218 219 if(sec_complete == 0 || data_prot == 0) 220 return read(fd, dataptr, length); 221 222 if(in_buffer.eof_flag){ 223 in_buffer.eof_flag = 0; 224 return 0; 225 } 226 227 len = buffer_read(&in_buffer, dataptr, length); 228 length -= len; 229 rx += len; 230 dataptr = (char*)dataptr + len; 231 232 while(length){ 233 int ret; 234 235 ret = sec_get_data(fd, &in_buffer, data_prot); 236 if (ret < 0) 237 return -1; 238 if(ret == 0 && in_buffer.size == 0) { 239 if(rx) 240 in_buffer.eof_flag = 1; 241 return rx; 242 } 243 len = buffer_read(&in_buffer, dataptr, length); 244 length -= len; 245 rx += len; 246 dataptr = (char*)dataptr + len; 247 } 248 return rx; 249 } 250 251 static int 252 sec_send(int fd, char *from, int length) 253 { 254 int bytes; 255 void *buf; 256 bytes = (*mech->encode)(app_data, from, length, data_prot, &buf); 257 bytes = htonl(bytes); 258 block_write(fd, &bytes, sizeof(bytes)); 259 block_write(fd, buf, ntohl(bytes)); 260 free(buf); 261 return length; 262 } 263 264 int 265 sec_fflush(FILE *F) 266 { 267 if(data_prot != prot_clear) { 268 if(out_buffer.index > 0){ 269 sec_write(fileno(F), out_buffer.data, out_buffer.index); 270 out_buffer.index = 0; 271 } 272 sec_send(fileno(F), NULL, 0); 273 } 274 fflush(F); 275 return 0; 276 } 277 278 int 279 sec_write(int fd, char *dataptr, int length) 280 { 281 int len = buffer_size; 282 int tx = 0; 283 284 if(data_prot == prot_clear) 285 return write(fd, dataptr, length); 286 287 len -= (*mech->overhead)(app_data, data_prot, len); 288 while(length){ 289 if(length < len) 290 len = length; 291 sec_send(fd, dataptr, len); 292 length -= len; 293 dataptr += len; 294 tx += len; 295 } 296 return tx; 297 } 298 299 int 300 sec_vfprintf2(FILE *f, const char *fmt, va_list ap) 301 { 302 char *buf; 303 int ret; 304 if(data_prot == prot_clear) 305 return vfprintf(f, fmt, ap); 306 else { 307 int len; 308 len = vasprintf(&buf, fmt, ap); 309 if (len == -1) 310 return len; 311 ret = buffer_write(&out_buffer, buf, len); 312 free(buf); 313 return ret; 314 } 315 } 316 317 int 318 sec_fprintf2(FILE *f, const char *fmt, ...) 319 { 320 int ret; 321 va_list ap; 322 va_start(ap, fmt); 323 ret = sec_vfprintf2(f, fmt, ap); 324 va_end(ap); 325 return ret; 326 } 327 328 int 329 sec_putc(int c, FILE *F) 330 { 331 char ch = c; 332 if(data_prot == prot_clear) 333 return putc(c, F); 334 335 buffer_write(&out_buffer, &ch, 1); 336 if(c == '\n' || out_buffer.index >= 1024 /* XXX */) { 337 sec_write(fileno(F), out_buffer.data, out_buffer.index); 338 out_buffer.index = 0; 339 } 340 return c; 341 } 342 343 int 344 sec_read_msg(char *s, int level) 345 { 346 int len; 347 char *buf; 348 int return_code; 349 350 buf = malloc(strlen(s)); 351 len = base64_decode(s + 4, buf); /* XXX */ 352 353 len = (*mech->decode)(app_data, buf, len, level); 354 if(len < 0) 355 return -1; 356 357 buf[len] = '\0'; 358 359 if(buf[3] == '-') 360 return_code = 0; 361 else 362 sscanf(buf, "%d", &return_code); 363 if(buf[len-1] == '\n') 364 buf[len-1] = '\0'; 365 strcpy(s, buf); 366 free(buf); 367 return return_code; 368 } 369 370 int 371 sec_vfprintf(FILE *f, const char *fmt, va_list ap) 372 { 373 char *buf; 374 void *enc; 375 int len; 376 if(!sec_complete) 377 return vfprintf(f, fmt, ap); 378 379 if (vasprintf(&buf, fmt, ap) == -1) { 380 printf("Failed to allocate command.\n"); 381 return -1; 382 } 383 len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc); 384 free(buf); 385 if(len < 0) { 386 printf("Failed to encode command.\n"); 387 return -1; 388 } 389 if(base64_encode(enc, len, &buf) < 0){ 390 free(enc); 391 printf("Out of memory base64-encoding.\n"); 392 return -1; 393 } 394 free(enc); 395 #ifdef FTP_SERVER 396 if(command_prot == prot_safe) 397 fprintf(f, "631 %s\r\n", buf); 398 else if(command_prot == prot_private) 399 fprintf(f, "632 %s\r\n", buf); 400 else if(command_prot == prot_confidential) 401 fprintf(f, "633 %s\r\n", buf); 402 #else 403 if(command_prot == prot_safe) 404 fprintf(f, "MIC %s", buf); 405 else if(command_prot == prot_private) 406 fprintf(f, "ENC %s", buf); 407 else if(command_prot == prot_confidential) 408 fprintf(f, "CONF %s", buf); 409 #endif 410 free(buf); 411 return 0; 412 } 413 414 int 415 sec_fprintf(FILE *f, const char *fmt, ...) 416 { 417 va_list ap; 418 int ret; 419 va_start(ap, fmt); 420 ret = sec_vfprintf(f, fmt, ap); 421 va_end(ap); 422 return ret; 423 } 424 425 /* end common stuff */ 426 427 #ifdef FTP_SERVER 428 429 int ccc_passed; 430 431 void 432 auth(char *auth_name) 433 { 434 int i; 435 void *tmp; 436 437 for(i = 0; (mech = mechs[i]) != NULL; i++){ 438 if(!strcasecmp(auth_name, mech->name)){ 439 tmp = realloc(app_data, mech->size); 440 if (tmp == NULL) { 441 reply(431, "Unable to accept %s at this time", mech->name); 442 return; 443 } 444 app_data = tmp; 445 446 if(mech->init && (*mech->init)(app_data) != 0) { 447 reply(431, "Unable to accept %s at this time", mech->name); 448 return; 449 } 450 if(mech->auth) { 451 (*mech->auth)(app_data); 452 return; 453 } 454 if(mech->adat) 455 reply(334, "Send authorization data."); 456 else 457 reply(234, "Authorization complete."); 458 return; 459 } 460 } 461 free (app_data); 462 app_data = NULL; 463 reply(504, "%s is unknown to me", auth_name); 464 } 465 466 void 467 adat(char *auth_data) 468 { 469 if(mech && !sec_complete) { 470 void *buf = malloc(strlen(auth_data)); 471 size_t len; 472 len = base64_decode(auth_data, buf); 473 (*mech->adat)(app_data, buf, len); 474 free(buf); 475 } else 476 reply(503, "You must %sissue an AUTH first.", mech ? "re-" : ""); 477 } 478 479 void pbsz(int size) 480 { 481 size_t new = size; 482 if(!sec_complete) 483 reply(503, "Incomplete security data exchange."); 484 if(mech->pbsz) 485 new = (*mech->pbsz)(app_data, size); 486 if(buffer_size != new){ 487 buffer_size = size; 488 } 489 if(new != size) 490 reply(200, "PBSZ=%lu", (unsigned long)new); 491 else 492 reply(200, "OK"); 493 } 494 495 void 496 prot(char *pl) 497 { 498 int p = -1; 499 500 if(buffer_size == 0){ 501 reply(503, "No protection buffer size negotiated."); 502 return; 503 } 504 505 if(!strcasecmp(pl, "C")) 506 p = prot_clear; 507 else if(!strcasecmp(pl, "S")) 508 p = prot_safe; 509 else if(!strcasecmp(pl, "E")) 510 p = prot_confidential; 511 else if(!strcasecmp(pl, "P")) 512 p = prot_private; 513 else { 514 reply(504, "Unrecognized protection level."); 515 return; 516 } 517 518 if(sec_complete){ 519 if((*mech->check_prot)(app_data, p)){ 520 reply(536, "%s does not support %s protection.", 521 mech->name, level_to_name(p)); 522 }else{ 523 data_prot = (enum protection_level)p; 524 reply(200, "Data protection is %s.", level_to_name(p)); 525 } 526 }else{ 527 reply(503, "Incomplete security data exchange."); 528 } 529 } 530 531 void ccc(void) 532 { 533 if(sec_complete){ 534 if(mech->ccc && (*mech->ccc)(app_data) == 0) { 535 command_prot = data_prot = prot_clear; 536 ccc_passed = 1; 537 } else 538 reply(534, "You must be joking."); 539 }else 540 reply(503, "Incomplete security data exchange."); 541 } 542 543 void mec(char *msg, enum protection_level level) 544 { 545 void *buf; 546 size_t len, buf_size; 547 if(!sec_complete) { 548 reply(503, "Incomplete security data exchange."); 549 return; 550 } 551 buf_size = strlen(msg) + 2; 552 buf = malloc(buf_size); 553 if (buf == NULL) { 554 reply(501, "Failed to allocate %lu", (unsigned long)buf_size); 555 return; 556 } 557 len = base64_decode(msg, buf); 558 command_prot = level; 559 if(len == (size_t)-1) { 560 free(buf); 561 reply(501, "Failed to base64-decode command"); 562 return; 563 } 564 len = (*mech->decode)(app_data, buf, len, level); 565 if(len == (size_t)-1) { 566 free(buf); 567 reply(535, "Failed to decode command"); 568 return; 569 } 570 ((char*)buf)[len] = '\0'; 571 if(strstr((char*)buf, "\r\n") == NULL) 572 strlcat((char*)buf, "\r\n", buf_size); 573 new_ftp_command(buf); 574 } 575 576 /* ------------------------------------------------------------ */ 577 578 int 579 sec_userok(char *userstr) 580 { 581 if(sec_complete) 582 return (*mech->userok)(app_data, userstr); 583 return 0; 584 } 585 586 int 587 sec_session(char *user) 588 { 589 if(sec_complete && mech->session) 590 return (*mech->session)(app_data, user); 591 return 0; 592 } 593 594 char *ftp_command; 595 596 void 597 new_ftp_command(char *command) 598 { 599 ftp_command = command; 600 } 601 602 void 603 delete_ftp_command(void) 604 { 605 free(ftp_command); 606 ftp_command = NULL; 607 } 608 609 int 610 secure_command(void) 611 { 612 return ftp_command != NULL; 613 } 614 615 enum protection_level 616 get_command_prot(void) 617 { 618 return command_prot; 619 } 620 621 #else /* FTP_SERVER */ 622 623 void 624 sec_status(void) 625 { 626 if(sec_complete){ 627 printf("Using %s for authentication.\n", mech->name); 628 printf("Using %s command channel.\n", level_to_name(command_prot)); 629 printf("Using %s data channel.\n", level_to_name(data_prot)); 630 if(buffer_size > 0) 631 printf("Protection buffer size: %lu.\n", 632 (unsigned long)buffer_size); 633 }else{ 634 printf("Not using any security mechanism.\n"); 635 } 636 } 637 638 static int 639 sec_prot_internal(int level) 640 { 641 int ret; 642 char *p; 643 unsigned int s = 1048576; 644 645 int old_verbose = verbose; 646 verbose = 0; 647 648 if(!sec_complete){ 649 printf("No security data exchange has taken place.\n"); 650 return -1; 651 } 652 653 if(level){ 654 ret = command("PBSZ %u", s); 655 if(ret != COMPLETE){ 656 printf("Failed to set protection buffer size.\n"); 657 return -1; 658 } 659 buffer_size = s; 660 p = strstr(reply_string, "PBSZ="); 661 if(p) 662 sscanf(p, "PBSZ=%u", &s); 663 if(s < buffer_size) 664 buffer_size = s; 665 } 666 verbose = old_verbose; 667 ret = command("PROT %c", level["CSEP"]); /* XXX :-) */ 668 if(ret != COMPLETE){ 669 printf("Failed to set protection level.\n"); 670 return -1; 671 } 672 673 data_prot = (enum protection_level)level; 674 return 0; 675 } 676 677 enum protection_level 678 set_command_prot(enum protection_level level) 679 { 680 int ret; 681 enum protection_level old = command_prot; 682 if(level != command_prot && level == prot_clear) { 683 ret = command("CCC"); 684 if(ret != COMPLETE) { 685 printf("Failed to clear command channel.\n"); 686 return prot_invalid; 687 } 688 } 689 command_prot = level; 690 return old; 691 } 692 693 void 694 sec_prot(int argc, char **argv) 695 { 696 int level = -1; 697 698 if(argc > 3) 699 goto usage; 700 701 if(argc == 1) { 702 sec_status(); 703 return; 704 } 705 if(!sec_complete) { 706 printf("No security data exchange has taken place.\n"); 707 code = -1; 708 return; 709 } 710 level = name_to_level(argv[argc - 1]); 711 712 if(level == -1) 713 goto usage; 714 715 if((*mech->check_prot)(app_data, level)) { 716 printf("%s does not implement %s protection.\n", 717 mech->name, level_to_name(level)); 718 code = -1; 719 return; 720 } 721 722 if(argc == 2 || strncasecmp(argv[1], "data", strlen(argv[1])) == 0) { 723 if(sec_prot_internal(level) < 0){ 724 code = -1; 725 return; 726 } 727 } else if(strncasecmp(argv[1], "command", strlen(argv[1])) == 0) { 728 if(set_command_prot(level) < 0) { 729 code = -1; 730 return; 731 } 732 } else 733 goto usage; 734 code = 0; 735 return; 736 usage: 737 printf("usage: %s [command|data] [clear|safe|confidential|private]\n", 738 argv[0]); 739 code = -1; 740 } 741 742 void 743 sec_prot_command(int argc, char **argv) 744 { 745 int level; 746 747 if(argc > 2) 748 goto usage; 749 750 if(!sec_complete) { 751 printf("No security data exchange has taken place.\n"); 752 code = -1; 753 return; 754 } 755 756 if(argc == 1) { 757 sec_status(); 758 } else { 759 level = name_to_level(argv[1]); 760 if(level == -1) 761 goto usage; 762 763 if((*mech->check_prot)(app_data, level)) { 764 printf("%s does not implement %s protection.\n", 765 mech->name, level_to_name(level)); 766 code = -1; 767 return; 768 } 769 if(set_command_prot(level) < 0) { 770 code = -1; 771 return; 772 } 773 } 774 code = 0; 775 return; 776 usage: 777 printf("usage: %s [clear|safe|confidential|private]\n", 778 argv[0]); 779 code = -1; 780 } 781 782 static enum protection_level request_data_prot; 783 784 void 785 sec_set_protection_level(void) 786 { 787 if(sec_complete && data_prot != request_data_prot) 788 sec_prot_internal(request_data_prot); 789 } 790 791 792 int 793 sec_request_prot(char *level) 794 { 795 int l = name_to_level(level); 796 if(l == -1) 797 return -1; 798 request_data_prot = (enum protection_level)l; 799 return 0; 800 } 801 802 int 803 sec_login(char *host) 804 { 805 int ret; 806 struct sec_client_mech **m; 807 int old_verbose = verbose; 808 809 verbose = -1; /* shut up all messages this will produce (they 810 are usually not very user friendly) */ 811 812 for(m = mechs; *m && (*m)->name; m++) { 813 void *tmp; 814 815 tmp = realloc(app_data, (*m)->size); 816 if (tmp == NULL) { 817 warnx ("realloc %lu failed", (unsigned long)(*m)->size); 818 return -1; 819 } 820 app_data = tmp; 821 822 if((*m)->init && (*(*m)->init)(app_data) != 0) { 823 printf("Skipping %s...\n", (*m)->name); 824 continue; 825 } 826 printf("Trying %s...\n", (*m)->name); 827 ret = command("AUTH %s", (*m)->name); 828 if(ret != CONTINUE){ 829 if(code == 504){ 830 printf("%s is not supported by the server.\n", (*m)->name); 831 }else if(code == 534){ 832 printf("%s rejected as security mechanism.\n", (*m)->name); 833 }else if(ret == ERROR) { 834 printf("The server doesn't support the FTP " 835 "security extensions.\n"); 836 verbose = old_verbose; 837 return -1; 838 } 839 continue; 840 } 841 842 ret = (*(*m)->auth)(app_data, host); 843 844 if(ret == AUTH_CONTINUE) 845 continue; 846 else if(ret != AUTH_OK){ 847 /* mechanism is supposed to output error string */ 848 verbose = old_verbose; 849 return -1; 850 } 851 mech = *m; 852 sec_complete = 1; 853 if(doencrypt) { 854 command_prot = prot_private; 855 request_data_prot = prot_private; 856 } else { 857 command_prot = prot_safe; 858 } 859 break; 860 } 861 862 verbose = old_verbose; 863 return *m == NULL; 864 } 865 866 void 867 sec_end(void) 868 { 869 if (mech != NULL) { 870 if(mech->end) 871 (*mech->end)(app_data); 872 if (app_data != NULL) { 873 memset(app_data, 0, mech->size); 874 free(app_data); 875 app_data = NULL; 876 } 877 } 878 sec_complete = 0; 879 data_prot = (enum protection_level)0; 880 } 881 882 #endif /* FTP_SERVER */ 883 884