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: security.c 21225 2007-06-20 10:16:02Z lha $"); 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 (enum protection_level)-1; 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 #ifdef KRB4 95 &krb4_server_mech, 96 #endif 97 NULL 98 }; 99 100 static struct sec_server_mech *mech; 101 102 #else 103 104 static struct sec_client_mech *mechs[] = { 105 #ifdef KRB5 106 &gss_client_mech, 107 #endif 108 #ifdef KRB4 109 &krb4_client_mech, 110 #endif 111 NULL 112 }; 113 114 static struct sec_client_mech *mech; 115 116 #endif 117 118 static void *app_data; 119 120 int 121 sec_getc(FILE *F) 122 { 123 if(sec_complete && data_prot) { 124 char c; 125 if(sec_read(fileno(F), &c, 1) <= 0) 126 return EOF; 127 return c; 128 } else 129 return getc(F); 130 } 131 132 static int 133 block_read(int fd, void *buf, size_t len) 134 { 135 unsigned char *p = buf; 136 int b; 137 while(len) { 138 b = read(fd, p, len); 139 if (b == 0) 140 return 0; 141 else if (b < 0) 142 return -1; 143 len -= b; 144 p += b; 145 } 146 return p - (unsigned char*)buf; 147 } 148 149 static int 150 block_write(int fd, void *buf, size_t len) 151 { 152 unsigned char *p = buf; 153 int b; 154 while(len) { 155 b = write(fd, p, len); 156 if(b < 0) 157 return -1; 158 len -= b; 159 p += b; 160 } 161 return p - (unsigned char*)buf; 162 } 163 164 static int 165 sec_get_data(int fd, struct buffer *buf, int level) 166 { 167 int len; 168 int b; 169 void *tmp; 170 171 b = block_read(fd, &len, sizeof(len)); 172 if (b == 0) 173 return 0; 174 else if (b < 0) 175 return -1; 176 len = ntohl(len); 177 tmp = realloc(buf->data, len); 178 if (tmp == NULL) 179 return -1; 180 buf->data = tmp; 181 b = block_read(fd, buf->data, len); 182 if (b == 0) 183 return 0; 184 else if (b < 0) 185 return -1; 186 buf->size = (*mech->decode)(app_data, buf->data, len, data_prot); 187 buf->index = 0; 188 return 0; 189 } 190 191 static size_t 192 buffer_read(struct buffer *buf, void *dataptr, size_t len) 193 { 194 len = min(len, buf->size - buf->index); 195 memcpy(dataptr, (char*)buf->data + buf->index, len); 196 buf->index += len; 197 return len; 198 } 199 200 static size_t 201 buffer_write(struct buffer *buf, void *dataptr, size_t len) 202 { 203 if(buf->index + len > buf->size) { 204 void *tmp; 205 if(buf->data == NULL) 206 tmp = malloc(1024); 207 else 208 tmp = realloc(buf->data, buf->index + len); 209 if(tmp == NULL) 210 return -1; 211 buf->data = tmp; 212 buf->size = buf->index + len; 213 } 214 memcpy((char*)buf->data + buf->index, dataptr, len); 215 buf->index += len; 216 return len; 217 } 218 219 int 220 sec_read(int fd, void *dataptr, int length) 221 { 222 size_t len; 223 int rx = 0; 224 225 if(sec_complete == 0 || data_prot == 0) 226 return read(fd, dataptr, length); 227 228 if(in_buffer.eof_flag){ 229 in_buffer.eof_flag = 0; 230 return 0; 231 } 232 233 len = buffer_read(&in_buffer, dataptr, length); 234 length -= len; 235 rx += len; 236 dataptr = (char*)dataptr + len; 237 238 while(length){ 239 int ret; 240 241 ret = sec_get_data(fd, &in_buffer, data_prot); 242 if (ret < 0) 243 return -1; 244 if(ret == 0 && in_buffer.size == 0) { 245 if(rx) 246 in_buffer.eof_flag = 1; 247 return rx; 248 } 249 len = buffer_read(&in_buffer, dataptr, length); 250 length -= len; 251 rx += len; 252 dataptr = (char*)dataptr + len; 253 } 254 return rx; 255 } 256 257 static int 258 sec_send(int fd, char *from, int length) 259 { 260 int bytes; 261 void *buf; 262 bytes = (*mech->encode)(app_data, from, length, data_prot, &buf); 263 bytes = htonl(bytes); 264 block_write(fd, &bytes, sizeof(bytes)); 265 block_write(fd, buf, ntohl(bytes)); 266 free(buf); 267 return length; 268 } 269 270 int 271 sec_fflush(FILE *F) 272 { 273 if(data_prot != prot_clear) { 274 if(out_buffer.index > 0){ 275 sec_write(fileno(F), out_buffer.data, out_buffer.index); 276 out_buffer.index = 0; 277 } 278 sec_send(fileno(F), NULL, 0); 279 } 280 fflush(F); 281 return 0; 282 } 283 284 int 285 sec_write(int fd, char *dataptr, int length) 286 { 287 int len = buffer_size; 288 int tx = 0; 289 290 if(data_prot == prot_clear) 291 return write(fd, dataptr, length); 292 293 len -= (*mech->overhead)(app_data, data_prot, len); 294 while(length){ 295 if(length < len) 296 len = length; 297 sec_send(fd, dataptr, len); 298 length -= len; 299 dataptr += len; 300 tx += len; 301 } 302 return tx; 303 } 304 305 int 306 sec_vfprintf2(FILE *f, const char *fmt, va_list ap) 307 { 308 char *buf; 309 int ret; 310 if(data_prot == prot_clear) 311 return vfprintf(f, fmt, ap); 312 else { 313 int len; 314 len = vasprintf(&buf, fmt, ap); 315 if (len == -1) 316 return len; 317 ret = buffer_write(&out_buffer, buf, len); 318 free(buf); 319 return ret; 320 } 321 } 322 323 int 324 sec_fprintf2(FILE *f, const char *fmt, ...) 325 { 326 int ret; 327 va_list ap; 328 va_start(ap, fmt); 329 ret = sec_vfprintf2(f, fmt, ap); 330 va_end(ap); 331 return ret; 332 } 333 334 int 335 sec_putc(int c, FILE *F) 336 { 337 char ch = c; 338 if(data_prot == prot_clear) 339 return putc(c, F); 340 341 buffer_write(&out_buffer, &ch, 1); 342 if(c == '\n' || out_buffer.index >= 1024 /* XXX */) { 343 sec_write(fileno(F), out_buffer.data, out_buffer.index); 344 out_buffer.index = 0; 345 } 346 return c; 347 } 348 349 int 350 sec_read_msg(char *s, int level) 351 { 352 int len; 353 char *buf; 354 int return_code; 355 356 buf = malloc(strlen(s)); 357 len = base64_decode(s + 4, buf); /* XXX */ 358 359 len = (*mech->decode)(app_data, buf, len, level); 360 if(len < 0) 361 return -1; 362 363 buf[len] = '\0'; 364 365 if(buf[3] == '-') 366 return_code = 0; 367 else 368 sscanf(buf, "%d", &return_code); 369 if(buf[len-1] == '\n') 370 buf[len-1] = '\0'; 371 strcpy(s, buf); 372 free(buf); 373 return return_code; 374 } 375 376 int 377 sec_vfprintf(FILE *f, const char *fmt, va_list ap) 378 { 379 char *buf; 380 void *enc; 381 int len; 382 if(!sec_complete) 383 return vfprintf(f, fmt, ap); 384 385 if (vasprintf(&buf, fmt, ap) == -1) { 386 printf("Failed to allocate command.\n"); 387 return -1; 388 } 389 len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc); 390 free(buf); 391 if(len < 0) { 392 printf("Failed to encode command.\n"); 393 return -1; 394 } 395 if(base64_encode(enc, len, &buf) < 0){ 396 free(enc); 397 printf("Out of memory base64-encoding.\n"); 398 return -1; 399 } 400 free(enc); 401 #ifdef FTP_SERVER 402 if(command_prot == prot_safe) 403 fprintf(f, "631 %s\r\n", buf); 404 else if(command_prot == prot_private) 405 fprintf(f, "632 %s\r\n", buf); 406 else if(command_prot == prot_confidential) 407 fprintf(f, "633 %s\r\n", buf); 408 #else 409 if(command_prot == prot_safe) 410 fprintf(f, "MIC %s", buf); 411 else if(command_prot == prot_private) 412 fprintf(f, "ENC %s", buf); 413 else if(command_prot == prot_confidential) 414 fprintf(f, "CONF %s", buf); 415 #endif 416 free(buf); 417 return 0; 418 } 419 420 int 421 sec_fprintf(FILE *f, const char *fmt, ...) 422 { 423 va_list ap; 424 int ret; 425 va_start(ap, fmt); 426 ret = sec_vfprintf(f, fmt, ap); 427 va_end(ap); 428 return ret; 429 } 430 431 /* end common stuff */ 432 433 #ifdef FTP_SERVER 434 435 int ccc_passed; 436 437 void 438 auth(char *auth_name) 439 { 440 int i; 441 void *tmp; 442 443 for(i = 0; (mech = mechs[i]) != NULL; i++){ 444 if(!strcasecmp(auth_name, mech->name)){ 445 tmp = realloc(app_data, mech->size); 446 if (tmp == NULL) { 447 reply(431, "Unable to accept %s at this time", mech->name); 448 return; 449 } 450 app_data = tmp; 451 452 if(mech->init && (*mech->init)(app_data) != 0) { 453 reply(431, "Unable to accept %s at this time", mech->name); 454 return; 455 } 456 if(mech->auth) { 457 (*mech->auth)(app_data); 458 return; 459 } 460 if(mech->adat) 461 reply(334, "Send authorization data."); 462 else 463 reply(234, "Authorization complete."); 464 return; 465 } 466 } 467 free (app_data); 468 app_data = NULL; 469 reply(504, "%s is unknown to me", auth_name); 470 } 471 472 void 473 adat(char *auth_data) 474 { 475 if(mech && !sec_complete) { 476 void *buf = malloc(strlen(auth_data)); 477 size_t len; 478 len = base64_decode(auth_data, buf); 479 (*mech->adat)(app_data, buf, len); 480 free(buf); 481 } else 482 reply(503, "You must %sissue an AUTH first.", mech ? "re-" : ""); 483 } 484 485 void pbsz(int size) 486 { 487 size_t new = size; 488 if(!sec_complete) 489 reply(503, "Incomplete security data exchange."); 490 if(mech->pbsz) 491 new = (*mech->pbsz)(app_data, size); 492 if(buffer_size != new){ 493 buffer_size = size; 494 } 495 if(new != size) 496 reply(200, "PBSZ=%lu", (unsigned long)new); 497 else 498 reply(200, "OK"); 499 } 500 501 void 502 prot(char *pl) 503 { 504 int p = -1; 505 506 if(buffer_size == 0){ 507 reply(503, "No protection buffer size negotiated."); 508 return; 509 } 510 511 if(!strcasecmp(pl, "C")) 512 p = prot_clear; 513 else if(!strcasecmp(pl, "S")) 514 p = prot_safe; 515 else if(!strcasecmp(pl, "E")) 516 p = prot_confidential; 517 else if(!strcasecmp(pl, "P")) 518 p = prot_private; 519 else { 520 reply(504, "Unrecognized protection level."); 521 return; 522 } 523 524 if(sec_complete){ 525 if((*mech->check_prot)(app_data, p)){ 526 reply(536, "%s does not support %s protection.", 527 mech->name, level_to_name(p)); 528 }else{ 529 data_prot = (enum protection_level)p; 530 reply(200, "Data protection is %s.", level_to_name(p)); 531 } 532 }else{ 533 reply(503, "Incomplete security data exchange."); 534 } 535 } 536 537 void ccc(void) 538 { 539 if(sec_complete){ 540 if(mech->ccc && (*mech->ccc)(app_data) == 0) { 541 command_prot = data_prot = prot_clear; 542 ccc_passed = 1; 543 } else 544 reply(534, "You must be joking."); 545 }else 546 reply(503, "Incomplete security data exchange."); 547 } 548 549 void mec(char *msg, enum protection_level level) 550 { 551 void *buf; 552 size_t len, buf_size; 553 if(!sec_complete) { 554 reply(503, "Incomplete security data exchange."); 555 return; 556 } 557 buf_size = strlen(msg) + 2; 558 buf = malloc(buf_size); 559 len = base64_decode(msg, buf); 560 command_prot = level; 561 if(len == (size_t)-1) { 562 reply(501, "Failed to base64-decode command"); 563 return; 564 } 565 len = (*mech->decode)(app_data, buf, len, level); 566 if(len == (size_t)-1) { 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 -1; 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