1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * gssutil.c 10 * 11 * Utility routines for providing security related services to 12 * the FTP server. This code uses the GSSAPI (RFC 2743, 2744) 13 * to provide a generic security layer to the application. The 14 * security mechanism providing the actual security functions 15 * is abstracted from the application itself. In the case of the FTP 16 * server, the security mechanism is based on what the client chooses 17 * to use when it makes the secure connection. If the client's 18 * choice of GSS mechanism is not supported by the FTP server, the 19 * connection may be rejected or fall back to standard Unix/PAM 20 * authentication. 21 * 22 * This code is primarily intended to work with clients who choose 23 * the Kerberos V5 GSSAPI mechanism as their security service. 24 */ 25 26 #include "config.h" 27 28 #if defined(USE_GSS) 29 #include <stdio.h> 30 #include <string.h> 31 #include <sys/types.h> 32 #include <ctype.h> 33 #include <stdlib.h> 34 #include <signal.h> 35 #include <pwd.h> 36 37 #include <netinet/in.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/ip.h> 40 41 #include <errno.h> 42 #include <sys/param.h> 43 #include <netdb.h> 44 #ifdef HAVE_SYS_SYSLOG_H 45 #include <sys/syslog.h> 46 #endif 47 48 /* CSTYLED */ 49 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H)) 50 #include <syslog.h> 51 #endif 52 53 #ifdef HAVE_SYSINFO 54 #include <sys/systeminfo.h> 55 #endif 56 57 #include <arpa/ftp.h> 58 59 #include "gssutil.h" 60 #include "proto.h" 61 62 static char *gss_services[] = { "ftp", "host", 0 }; 63 64 gss_info_t gss_info = { 65 /* context */ GSS_C_NO_CONTEXT, 66 /* mechoid */ GSS_C_NULL_OID, 67 /* client */ NULL, 68 /* display_name */ NULL, 69 /* data_prot */ PROT_C, 70 /* ctrl_prot */ PROT_C, 71 /* authstate */ GSS_AUTH_NONE, 72 /* want_creds */ 0, 73 /* have_creds */ 0, 74 /* must_auth */ 0 75 }; 76 77 78 extern char *cur_auth_type; 79 extern struct SOCKSTORAGE his_addr; 80 extern struct SOCKSTORAGE ctrl_addr; 81 extern int debug; 82 83 static char *radixN = 84 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 85 86 static char pad = '='; 87 88 #define DEF_GSSBUF_SIZE 2028 89 #define DECODELEN(l) (((3 * (l)) / 4) + 4) 90 #define ENCODELEN(l) (((4 * (l)) / 3) + 4) 91 92 typedef struct { 93 char *buf; 94 size_t alloc_len; 95 size_t len; /* max length of buffer */ 96 size_t idx; /* offset to beginning of read/write data */ 97 size_t clen; /* length of the remaining, decrypted data from client */ 98 }bufrec; 99 100 static bufrec obr = {NULL, 0, 0, 0, 0}; 101 static bufrec ibr = {NULL, 0, 0, 0, 0}; 102 103 static int looping_write(int fd, const char *buf, size_t len); 104 static int looping_read(int fd, char *buf, size_t len); 105 static int radix_encode(unsigned char *inbuf, unsigned char *outbuf, 106 size_t len, int *outlen, int decode); 107 static char *radix_error(int e); 108 static void reply_gss_error(int code, OM_uint32 maj_stat, 109 OM_uint32 min_stat, gss_OID mechoid, char *s); 110 static void cleanup_bufrec(bufrec *brec); 111 static int alloc_bufrec(bufrec *brec, size_t newsz); 112 static int sec_putbuf(int fd, unsigned char *buf, int len); 113 static int sec_getbytes(int fd, char *buf, int nbytes); 114 115 /* 116 * Provide a routine so that ftpd can know the max amount to read 117 */ 118 size_t 119 gss_getinbufsz(void) { 120 return (ibr.len); 121 } 122 123 /* 124 * gss_adjust_buflen 125 * 126 * Called when the protection method changes so we can adjust the 127 * "useable" length of our output buffer accordingly. 128 */ 129 void 130 gss_adjust_buflen() 131 { 132 OM_uint32 maj_stat, min_stat, mlen; 133 134 /* 135 * If we switched to CLEAR protection, we can use the entire buffer 136 */ 137 if (gss_info.data_prot == PROT_C) { 138 obr.len = obr.alloc_len; 139 return; 140 } 141 142 /* 143 * Otherwise, determine the maximum size that will allow for 144 * the GSSAPI overhead to fit into the buffer size. 145 */ 146 maj_stat = gss_wrap_size_limit(&min_stat, gss_info.context, 147 (gss_info.data_prot == PROT_P), 148 GSS_C_QOP_DEFAULT, 149 (OM_uint32)obr.alloc_len, &mlen); 150 if (maj_stat != GSS_S_COMPLETE) { 151 reply_gss_error(535, maj_stat, min_stat, 152 gss_info.mechoid, 153 "GSSAPI fudge determination"); 154 return; 155 } 156 obr.len = mlen; 157 158 if (debug) 159 syslog(LOG_DEBUG, "GSSAPI alloc_len = %d len = %d", 160 obr.alloc_len, obr.len); 161 } 162 163 static int 164 looping_write(int fd, const char *buf, size_t len) 165 { 166 int cc; 167 register size_t wrlen = len; 168 169 do { 170 cc = write(fd, buf, wrlen); 171 if (cc < 0) { 172 if (errno == EINTR) 173 continue; 174 return (cc); 175 } else { 176 buf += cc; 177 wrlen -= cc; 178 } 179 } while (wrlen > 0); 180 181 return (len); 182 } 183 184 static int 185 looping_read(int fd, char *buf, size_t len) 186 { 187 int cc; 188 size_t len2 = 0; 189 190 do { 191 cc = read(fd, buf, len); 192 if (cc < 0) { 193 if (errno == EINTR) 194 continue; 195 return (cc); /* errno is already set */ 196 } else if (cc == 0) { 197 return (len2); 198 } else { 199 buf += cc; 200 len2 += cc; 201 len -= cc; 202 } 203 } while (len > 0); 204 return (len2); 205 } 206 207 static int 208 radix_encode(unsigned char *inbuf, unsigned char *outbuf, 209 size_t buflen, int *outlen, int decode) 210 { 211 register int i, j, D; 212 char *p; 213 unsigned char c; 214 215 if (decode) { 216 for (i = 0, j = 0; (j < buflen) && 217 inbuf[i] && inbuf[i] != pad; i++) { 218 if ((p = strchr(radixN, inbuf[i])) == NULL) 219 return (1); 220 D = p - radixN; 221 switch (i&3) { 222 case 0: 223 outbuf[j] = D <<2; 224 break; 225 case 1: 226 outbuf[j++] |= D >>4; 227 outbuf[j] = (D&15)<<4; 228 break; 229 case 2: 230 outbuf[j++] |= D >>2; 231 outbuf[j] = (D&3)<<6; 232 break; 233 case 3: 234 outbuf[j++] |= D; 235 } 236 } 237 if (j == buflen && (inbuf[i] && inbuf[i] != pad)) { 238 /* Oops, we ran out of space in the output buffer */ 239 return (4); 240 } 241 switch (i&3) { 242 case 1: 243 return (3); 244 case 2: if (D&15) 245 return (3); 246 if (strcmp((char *)&inbuf[i], "==")) 247 return (2); 248 break; 249 case 3: if (D&3) 250 return (3); 251 if (strcmp((char *)&inbuf[i], "=")) 252 return (2); 253 } 254 *outlen = j; 255 } else { 256 for (i = 0, j = 0; i < *outlen && j < buflen; i++) 257 switch (i%3) { 258 case 0: 259 outbuf[j++] = radixN[inbuf[i]>>2]; 260 c = (inbuf[i]&3)<<4; 261 break; 262 case 1: 263 outbuf[j++] = radixN[c|inbuf[i]>>4]; 264 c = (inbuf[i]&15)<<2; 265 break; 266 case 2: 267 outbuf[j++] = radixN[c|inbuf[i]>>6]; 268 outbuf[j++] = radixN[inbuf[i]&63]; 269 c = 0; 270 } 271 if (j == buflen && i < *outlen) { 272 /* output buffer is not big enough */ 273 return (4); 274 } 275 276 if (i%3) outbuf[j++] = radixN[c]; 277 switch (i%3) { 278 case 1: outbuf[j++] = pad; 279 case 2: outbuf[j++] = pad; 280 } 281 outbuf[*outlen = j] = '\0'; 282 } 283 return (0); 284 } 285 286 static char * 287 radix_error(int e) 288 { 289 switch (e) { 290 case 0: return ("Success"); 291 case 1: return ("Bad character in encoding"); 292 case 2: return ("Encoding not properly padded"); 293 case 3: return ("Decoded # of bits not a multiple of 8"); 294 case 4: return ("Buffer size error"); 295 default: return ("Unknown error"); 296 } 297 } 298 299 static void 300 reply_gss_error(int code, OM_uint32 maj_stat, 301 OM_uint32 min_stat, gss_OID mechoid, char *s) 302 { 303 /* a lot of work just to report the error */ 304 OM_uint32 gmaj_stat, gmin_stat; 305 gss_buffer_desc msg; 306 int msg_ctx; 307 msg_ctx = 0; 308 309 gmaj_stat = gss_display_status(&gmin_stat, maj_stat, 310 GSS_C_GSS_CODE, 311 mechoid, 312 (OM_uint32 *)&msg_ctx, &msg); 313 if (gmaj_stat == GSS_S_COMPLETE) { 314 lreply(code, "GSSAPI error major: %s", 315 (char *)msg.value); 316 (void) gss_release_buffer(&gmin_stat, &msg); 317 } 318 319 gmaj_stat = gss_display_status(&gmin_stat, min_stat, 320 GSS_C_MECH_CODE, 321 mechoid, 322 (OM_uint32 *)&msg_ctx, &msg); 323 if (gmaj_stat == GSS_S_COMPLETE) { 324 lreply(code, "GSSAPI error minor: %s", (char *)msg.value); 325 (void) gss_release_buffer(&gmin_stat, &msg); 326 } 327 328 reply(code, "GSSAPI error: %s", s); 329 } 330 331 332 static void 333 log_status(char *msg, 334 OM_uint32 status_code, 335 int status_type) 336 { 337 OM_uint32 message_context; 338 gss_buffer_desc status_string; 339 OM_uint32 maj_status; 340 OM_uint32 min_status; 341 342 /* From RFC2744: */ 343 message_context = 0; 344 345 do { 346 maj_status = gss_display_status( 347 &min_status, 348 status_code, 349 status_type, 350 GSS_C_NO_OID, 351 &message_context, 352 &status_string); 353 354 if (maj_status == GSS_S_COMPLETE) { 355 syslog(LOG_ERR, 356 "GSSAPI Error %s: %.*s\n", 357 msg ? msg : "<null>", 358 (int)status_string.length, 359 (char *)status_string.value); 360 361 (void) gss_release_buffer(&min_status, 362 &status_string); 363 } else { 364 syslog(LOG_ERR, 365 "log_status internal error: gss_display_status failed"); 366 return; 367 } 368 } while (message_context != 0); 369 370 } 371 372 static void 373 log_gss_error(char *msg, 374 OM_uint32 maj_stat, 375 OM_uint32 min_stat) 376 { 377 log_status(msg, maj_stat, GSS_C_GSS_CODE); 378 log_status(msg, min_stat, GSS_C_MECH_CODE); 379 } 380 381 382 static void 383 log_gss_info(int priority, 384 char *luser, 385 char *remprinc, 386 gss_OID mechoid, 387 char *s) 388 { 389 const char *mechStr = __gss_oid_to_mech(mechoid); 390 391 syslog(priority, 392 "%s: local user=`%s', remote princ=`%s', mech=%s", 393 s ? s : "<null>", 394 luser ? luser : "<null>", 395 remprinc ? remprinc : "<unknown>", 396 mechStr ? mechStr : "<unknown>"); 397 } 398 399 /* 400 * gss_user 401 * 402 * Handle USER command after AUTH GSSAPI 403 * 404 * Check if the remote user can login to the local system w/out a passwd. 405 * Use the Solaris (private) interface (__gss_userok) if possible, else do 406 * a basic GSS-API compare. 407 * 408 * return 0 == BAD 409 * 1 == OK 410 */ 411 int 412 gss_user(struct passwd *user_pw) 413 { 414 int retval = 0; 415 OM_uint32 status, minor; 416 417 #ifdef SOLARIS_GSS_USEROK 418 419 int user_ok = 0; 420 421 if (debug) 422 log_gss_info(LOG_DEBUG, 423 user_pw->pw_name, gss_info.display_name, 424 gss_info.mechoid, 425 "gss_user: start (gss_userok)"); 426 427 /* gss_auth_rules(5) */ 428 status = __gss_userok(&minor, gss_info.client, 429 user_pw->pw_name, &user_ok); 430 if (status == GSS_S_COMPLETE) { 431 if (user_ok) { 432 retval = 1; /* remote user is a-ok */ 433 } 434 } 435 436 #else /* SOLARIS_GSS_USEROK */ 437 438 gss_name_t imported_name; 439 gss_name_t canon_name; 440 gss_buffer_desc gss_user; 441 OM_uint32 tmpMinor; 442 int match = 0; 443 444 if (debug) 445 log_gss_info(LOG_DEBUG, 446 user_pw->pw_name, gss_info.display_name, 447 gss_info.mechoid, "gss_user: start"); 448 449 gss_user.value = user_pw->pw_name; 450 gss_user.length = strlen(gss_user.value); 451 452 status = gss_import_name(&minor, 453 &gss_user, 454 GSS_C_NT_USER_NAME, 455 &imported_name); 456 if (status != GSS_S_COMPLETE) { 457 goto out; 458 } 459 460 status = gss_canonicalize_name(&minor, 461 imported_name, 462 gss_info.mechoid, 463 &canon_name); 464 if (status != GSS_S_COMPLETE) { 465 (void) gss_release_name(&tmpMinor, &imported_name); 466 goto out; 467 } 468 469 status = gss_compare_name(&minor, 470 canon_name, 471 gss_info.client, 472 &match); 473 (void) gss_release_name(&tmpMinor, &canon_name); 474 (void) gss_release_name(&tmpMinor, &imported_name); 475 if (status == GSS_S_COMPLETE) { 476 if (match) { 477 retval = 1; /* remote user is a-ok */ 478 } 479 } 480 481 out: 482 483 #endif /* SOLARIS_GSS_USEROK */ 484 485 if (status != GSS_S_COMPLETE) { 486 log_gss_info(LOG_ERR, user_pw->pw_name, 487 gss_info.display_name, gss_info.mechoid, 488 "gss_user failed"); 489 log_gss_error("gss_user failed", status, minor); 490 } 491 492 if (debug) 493 syslog(LOG_DEBUG, "gss_user: end: retval=%d", retval); 494 495 return (retval); 496 } 497 498 499 /* 500 * gss_adat 501 * 502 * Handle ADAT(Authentication Data) command data. 503 */ 504 int 505 gss_adat(char *adatstr) 506 { 507 int kerror, length; 508 int replied = 0; 509 int ret_flags; 510 gss_buffer_desc tok, out_tok; 511 gss_cred_id_t deleg_creds = NULL; 512 OM_uint32 accept_maj, accept_min; 513 OM_uint32 stat_maj, stat_min; 514 uchar_t *gout_buf; 515 size_t outlen; 516 517 length = strlen(adatstr); 518 outlen = DECODELEN(length); 519 520 gout_buf = (uchar_t *)malloc(outlen); 521 if (gout_buf == NULL) { 522 reply(501, "Couldn't decode ADAT, not enough memory"); 523 syslog(LOG_ERR, "Couldn't decode ADAT, not enough memory"); 524 return (0); 525 } 526 527 if ((kerror = radix_encode((unsigned char *)adatstr, 528 (unsigned char *)gout_buf, 529 outlen, &length, 1))) { 530 reply(501, "Couldn't decode ADAT(%s)", 531 radix_error(kerror)); 532 syslog(LOG_ERR, "Couldn't decode ADAT(%s)", 533 radix_error(kerror)); 534 return (0); 535 } 536 tok.value = gout_buf; 537 tok.length = length; 538 539 gss_info.context = GSS_C_NO_CONTEXT; 540 541 /* 542 * Call accept_sec_context w/GSS_C_NO_CREDENTIAL to request 543 * default cred and to not limit the service name to one name 544 * but rather accept what the clnt requests if service 545 * princ/keys are available. 546 */ 547 if (debug) 548 syslog(LOG_DEBUG, 549 "gss_adat: accept_sec_context will try default cred"); 550 551 out_tok.value = NULL; 552 out_tok.length = 0; 553 554 accept_maj = gss_accept_sec_context(&accept_min, 555 &gss_info.context, 556 GSS_C_NO_CREDENTIAL, 557 &tok, /* ADAT data */ 558 GSS_C_NO_CHANNEL_BINDINGS, 559 &gss_info.client, 560 &gss_info.mechoid, 561 &out_tok, /* output_token */ 562 (unsigned int *)&ret_flags, 563 NULL, /* ignore time_rec */ 564 NULL); /* delegated creds */ 565 566 567 if (debug) { 568 if (accept_maj == GSS_S_COMPLETE) 569 syslog(LOG_DEBUG, 570 "gss_adat: accept_maj = GSS_S_COMPLETE"); 571 else if (accept_maj == GSS_S_CONTINUE_NEEDED) 572 syslog(LOG_DEBUG, 573 "gss_adat: accept_maj = GSS_S_CONTINUE_NEEDED"); 574 } 575 free(gout_buf); 576 577 if (accept_maj != GSS_S_COMPLETE && 578 accept_maj != GSS_S_CONTINUE_NEEDED) { 579 reply_gss_error(535, accept_maj, accept_min, 580 GSS_C_NO_OID, "accepting context"); 581 syslog(LOG_ERR, "failed accepting context"); 582 if ((ret_flags & GSS_C_DELEG_FLAG) && 583 deleg_creds != NULL) 584 (void) gss_release_cred(&stat_min, 585 &deleg_creds); 586 587 (void) gss_release_buffer(&stat_min, &out_tok); 588 return (0); 589 } 590 591 if (debug) 592 syslog(LOG_DEBUG, "gss_adat: out_tok.length=%d", 593 out_tok.length); 594 if (out_tok.length) { 595 size_t buflen = ENCODELEN(out_tok.length); 596 uchar_t *gbuf = (uchar_t *)malloc(buflen); 597 if (gbuf == NULL) { 598 reply(535, "Couldn't encode ADAT reply, " 599 "not enough memory."); 600 syslog(LOG_ERR, "Couldn't encode ADAT reply, " 601 "not enough memory."); 602 (void) gss_release_buffer(&stat_min, &out_tok); 603 return (0); 604 } 605 if ((kerror = radix_encode(out_tok.value, 606 (unsigned char *)gbuf, 607 buflen, (int *)&out_tok.length, 608 0))) { 609 reply(535, "Couldn't encode ADAT reply(%s)", 610 radix_error(kerror)); 611 syslog(LOG_ERR, "couldn't encode ADAT reply"); 612 if ((ret_flags & GSS_C_DELEG_FLAG) && 613 deleg_creds != NULL) 614 (void) gss_release_cred(&stat_min, 615 &deleg_creds); 616 617 (void) gss_release_buffer(&stat_min, &out_tok); 618 free(gbuf); 619 return (0); 620 } 621 622 if (accept_maj == GSS_S_COMPLETE) { 623 reply(235, "ADAT=%s", gbuf); 624 replied = 1; 625 } else { 626 /* 627 * If the server accepts the security data, and 628 * requires additional data, it should respond 629 * with reply code 335. 630 */ 631 reply(335, "ADAT=%s", gbuf); 632 } 633 free(gbuf); 634 (void) gss_release_buffer(&stat_min, &out_tok); 635 } 636 if (accept_maj == GSS_S_COMPLETE) { 637 gss_buffer_desc namebuf; 638 gss_OID out_oid; 639 640 /* GSSAPI authentication succeeded */ 641 gss_info.authstate = GSS_ADAT_DONE; 642 (void) alloc_bufrec(&obr, DEF_GSSBUF_SIZE); 643 (void) alloc_bufrec(&ibr, DEF_GSSBUF_SIZE); 644 /* 645 * RFC 2228 - "..., once a security data exchange completes 646 * successfully, if the security mechanism supports 647 * integrity, then integrity(via the MIC or ENC command, 648 * and 631 or 632 reply) must be used, ..." 649 */ 650 gss_info.ctrl_prot = PROT_S; 651 652 stat_maj = gss_display_name(&stat_min, gss_info.client, 653 &namebuf, &out_oid); 654 if (stat_maj != GSS_S_COMPLETE) { 655 /* 656 * RFC 2228 - 657 * "If the server rejects the security data(if 658 * a checksum fails, for instance), it should 659 * respond with reply code 535." 660 */ 661 reply_gss_error(535, stat_maj, stat_min, 662 gss_info.mechoid, 663 "extracting GSSAPI identity name"); 664 syslog(LOG_ERR, "gssapi error extracting identity"); 665 if ((ret_flags & GSS_C_DELEG_FLAG) && 666 deleg_creds != NULL) 667 (void) gss_release_cred(&stat_min, 668 &deleg_creds); 669 return (0); 670 } 671 gss_info.display_name = (char *)namebuf.value; 672 673 if (ret_flags & GSS_C_DELEG_FLAG) { 674 gss_info.have_creds = 1; 675 if (deleg_creds != NULL) 676 (void) gss_release_cred(&stat_min, 677 &deleg_creds); 678 } 679 680 /* 681 * If the server accepts the security data, but does 682 * not require any additional data(i.e., the security 683 * data exchange has completed successfully), it must 684 * respond with reply code 235. 685 */ 686 if (!replied) { 687 if ((ret_flags & GSS_C_DELEG_FLAG) && 688 !gss_info.have_creds) 689 reply(235, 690 "GSSAPI Authentication succeeded, but " 691 "could not accept forwarded credentials"); 692 else 693 reply(235, "GSSAPI Authentication succeeded"); 694 } 695 return (1); 696 } else if (accept_maj == GSS_S_CONTINUE_NEEDED) { 697 /* 698 * If the server accepts the security data, and 699 * requires additional data, it should respond with 700 * reply code 335. 701 */ 702 reply(335, "more data needed"); 703 if ((ret_flags & GSS_C_DELEG_FLAG) && 704 deleg_creds != NULL) 705 (void) gss_release_cred(&stat_min, &deleg_creds); 706 } 707 708 return (0); 709 } 710 711 /* 712 * cleanup_bufrec 713 * 714 * cleanup the secure buffers 715 */ 716 static void 717 cleanup_bufrec(bufrec *brec) 718 { 719 if (brec->buf) 720 free(brec->buf); 721 brec->len = 0; 722 brec->clen = 0; 723 brec->idx = 0; 724 } 725 726 static int 727 alloc_bufrec(bufrec *brec, size_t newsz) 728 { 729 /* 730 * Try to allocate a buffer, if it fails, 731 * divide by 2 and try again. 732 */ 733 cleanup_bufrec(brec); 734 735 while (newsz > 0 && !(brec->buf = malloc(newsz))) { 736 syslog(LOG_ERR, 737 "malloc bufrec(%d bytes) failed, trying %d", 738 newsz >>= 1); 739 } 740 741 if (brec->buf == NULL) 742 return (-1); 743 744 brec->alloc_len = newsz; 745 brec->len = newsz; 746 brec->clen = 0; 747 brec->idx = 0; 748 return (0); 749 } 750 751 /* 752 * Handle PBSZ command data, return value to caller. 753 * RFC 2228 says this is a 32 bit int, so limit max value here. 754 */ 755 unsigned int 756 gss_setpbsz(char *pbszstr) 757 { 758 unsigned int newsz = 0; 759 char *endp; 760 #define MAX_PBSZ 4294967295U 761 762 errno = 0; 763 newsz = (unsigned int)strtol(pbszstr, &endp, 10); 764 if (errno != 0 || newsz > MAX_PBSZ || *endp != '\0') { 765 reply(501, "Bad value for PBSZ: %s", pbszstr); 766 return (0); 767 } 768 769 if (newsz > ibr.len) { 770 if (alloc_bufrec(&obr, newsz) == -1) { 771 perror_reply(421, "Local resource failure: malloc"); 772 dologout(1); 773 } 774 if (alloc_bufrec(&ibr, newsz) == -1) { 775 perror_reply(421, "Local resource failure: malloc"); 776 dologout(1); 777 } 778 } 779 reply(200, "PBSZ =%lu", ibr.len); 780 781 return (ibr.len); 782 } 783 784 /* 785 * sec_putbuf 786 * 787 * Wrap the plaintext 'buf' data using gss_wrap and send 788 * it out. 789 * 790 * returns: 791 * bytes written (success) 792 * -1 on error(errno set) 793 * -2 on security error 794 */ 795 static int 796 sec_putbuf(int fd, unsigned char *buf, int len) 797 { 798 unsigned long net_len; 799 int ret = 0; 800 gss_buffer_desc in_buf, out_buf; 801 OM_uint32 maj_stat, min_stat; 802 int conf_state; 803 804 in_buf.value = buf; 805 in_buf.length = len; 806 maj_stat = gss_wrap(&min_stat, gss_info.context, 807 (gss_info.data_prot == PROT_P), 808 GSS_C_QOP_DEFAULT, 809 &in_buf, &conf_state, 810 &out_buf); 811 812 if (maj_stat != GSS_S_COMPLETE) { 813 reply_gss_error(535, maj_stat, min_stat, 814 gss_info.mechoid, 815 gss_info.data_prot == PROT_P ? 816 "GSSAPI wrap failed": 817 "GSSAPI sign failed"); 818 return (-2); 819 } 820 821 net_len = (unsigned long)htonl((unsigned long) out_buf.length); 822 823 if ((ret = looping_write(fd, (const char *)&net_len, 4)) != 4) { 824 syslog(LOG_ERR, "Error writing net_len(%d): %m", net_len); 825 ret = -1; 826 goto putbuf_done; 827 } 828 829 if ((ret = looping_write(fd, out_buf.value, out_buf.length)) != 830 out_buf.length) { 831 syslog(LOG_ERR, "Error writing %d bytes: %m", out_buf.length); 832 ret = -1; 833 goto putbuf_done; 834 } 835 putbuf_done: 836 837 gss_release_buffer(&min_stat, &out_buf); 838 return (ret); 839 } 840 841 /* 842 * sec_write 843 * 844 * If GSSAPI security is established, encode the output 845 * and write it to the client. Else, just write it directly. 846 */ 847 int 848 sec_write(int fd, char *buf, int len) 849 { 850 int nbytes = 0; 851 if (gss_info.data_prot == PROT_C || 852 !IS_GSSAUTH(cur_auth_type) || 853 !(gss_info.authstate & GSS_ADAT_DONE)) 854 nbytes = write(fd, buf, len); 855 else { 856 /* 857 * Fill up the buffer before actually encrypting 858 * and writing it out. 859 */ 860 while ((obr.idx < obr.len) && (len > 0)) { 861 int n, ret; 862 863 /* how many bytes can we fit into the buffer? */ 864 n = (len < (obr.len - obr.idx) ? len : 865 obr.len - obr.idx); 866 memcpy(obr.buf + obr.idx, buf, n); 867 868 obr.idx += n; 869 870 if (obr.idx >= obr.len) { 871 ret = sec_putbuf(fd, (unsigned char *)obr.buf, 872 obr.idx); 873 obr.idx = 0; 874 if (ret < 0) 875 return (ret); 876 } 877 len -= n; 878 nbytes += n; 879 } 880 } 881 882 return (nbytes); 883 } 884 885 /* 886 * CCC 887 * 888 * Clear Command Channel. 889 * 890 * We will understand this command but not allow it in a secure 891 * connection. It is very dangerous to allow someone to degrade 892 * the security of the command channel. See RFC2228 for more info. 893 */ 894 void 895 ccc(void) 896 { 897 /* 898 * Once we have negotiated security successfully, 899 * do not allow the control channel to be downgraded. 900 * It should be at least SAFE if not PRIVATE. 901 */ 902 if (IS_GSSAUTH(cur_auth_type) && 903 (gss_info.authstate & GSS_ADAT_DONE) == GSS_ADAT_DONE) 904 reply(534, "Control channel may not be downgraded"); 905 else { 906 gss_info.ctrl_prot = PROT_C; 907 reply(200, "CCC ok"); 908 } 909 } 910 911 int 912 sec_putc(int c, FILE *stream) 913 { 914 int ret = 0; 915 /* 916 * If we are NOT protecting the data 917 * OR not using the GSSAPI authentication 918 * OR GSSAPI data is not yet completed, send 919 * plaintext. 920 */ 921 if (gss_info.data_prot == PROT_C || 922 !IS_GSSAUTH(cur_auth_type) || 923 !(gss_info.authstate & GSS_ADAT_DONE)) 924 return (putc(c, stream)); 925 926 /* 927 * Add the latest byte to the current buffer 928 */ 929 if (obr.idx < obr.len) { 930 obr.buf[obr.idx++] = (unsigned char)(c & 0xff); 931 } 932 933 if (obr.idx == obr.len) { 934 ret = sec_putbuf(fileno(stream), (uchar_t *)obr.buf, obr.idx); 935 if (ret >= 0) 936 ret = 0; 937 obr.idx = 0; 938 } 939 940 return ((ret == 0 ? c : ret)); 941 } 942 943 int 944 sec_fprintf(FILE *stream, char *fmt, ...) 945 { 946 int ret; 947 va_list ap; 948 va_start(ap, fmt); 949 950 if (gss_info.data_prot == PROT_C || 951 !IS_GSSAUTH(cur_auth_type) || 952 !(gss_info.authstate & GSS_ADAT_DONE)) { 953 ret = vfprintf(stream, fmt, ap); 954 } else { 955 (void) vsnprintf(obr.buf, obr.len, fmt, ap); 956 ret = sec_putbuf(fileno(stream), (unsigned char *)obr.buf, 957 strlen(obr.buf)); 958 } 959 va_end(ap); 960 return (ret); 961 } 962 963 /* 964 * sec_fflush 965 * 966 * If GSSAPI protection is configured, write out whatever remains 967 * in the output buffer using the secure routines, otherwise 968 * just flush the stream. 969 */ 970 int 971 sec_fflush(FILE *stream) 972 { 973 int ret = 0; 974 if (gss_info.data_prot == PROT_C || 975 !IS_GSSAUTH(cur_auth_type) || 976 !(gss_info.authstate & GSS_ADAT_DONE)) { 977 fflush(stream); 978 return (0); 979 } 980 if (obr.idx > 0) { 981 ret = sec_putbuf(fileno(stream), 982 (unsigned char *)obr.buf, obr.idx); 983 obr.idx = 0; 984 } 985 986 if (ret >= 0) 987 ret = sec_putbuf(fileno(stream), (unsigned char *)"", 0); 988 /* 989 * putbuf returns number of bytes or a negative value, 990 * but fflush must return 0 or -1, so adjust the return 991 * value so that a positive value is interpreted as success. 992 */ 993 return (ret >= 0 ? 0 : ret); 994 } 995 996 /* 997 * sec_getbytes 998 * 999 * Read and decrypt from the secure data channel. 1000 * 1001 * Return: 1002 * > 0 == number of bytes available in gssbuf 1003 * EOF == End of file. 1004 * -2 == GSS error. 1005 * 1006 */ 1007 static int 1008 sec_getbytes(int fd, char *buf, int nbytes) 1009 { 1010 /* 1011 * Only read from the network if our current buffer 1012 * is all used up. 1013 */ 1014 if (ibr.idx >= ibr.clen) { 1015 int kerror; 1016 int conf_state; 1017 unsigned int length; 1018 gss_buffer_desc xmit_buf, msg_buf; 1019 OM_uint32 maj_stat, min_stat; 1020 1021 if ((kerror = looping_read(fd, (char *)&length, 4)) != 4) { 1022 reply(535, "Couldn't read PROT buffer length: %d/%s", 1023 kerror, 1024 (kerror == -1) ? strerror(errno) : "premature EOF"); 1025 return (-2); 1026 } 1027 1028 if ((length = (unsigned int)ntohl(length)) > ibr.len) { 1029 reply(535, "Length(%d) > PBSZ(%d)", length, ibr.len); 1030 return (-2); 1031 } 1032 1033 if (length > 0) { 1034 if ((kerror = looping_read(fd, ibr.buf, length)) != 1035 length) { 1036 reply(535, "Couldn't read %u byte PROT buf: %s", 1037 length, (kerror == -1) ? 1038 strerror(errno) : "premature EOF"); 1039 return (-2); 1040 } 1041 1042 xmit_buf.value = (char *)ibr.buf; 1043 xmit_buf.length = length; 1044 1045 conf_state = (gss_info.data_prot == PROT_P); 1046 1047 /* decrypt/verify the message */ 1048 maj_stat = gss_unwrap(&min_stat, gss_info.context, 1049 &xmit_buf, &msg_buf, &conf_state, NULL); 1050 if (maj_stat != GSS_S_COMPLETE) { 1051 reply_gss_error(535, maj_stat, min_stat, 1052 gss_info.mechoid, 1053 (gss_info.data_prot == PROT_P)? 1054 "failed unwrapping ENC message": 1055 "failed unwrapping MIC message"); 1056 return (-2); 1057 } 1058 1059 memcpy(ibr.buf, msg_buf.value, msg_buf.length); 1060 ibr.clen = msg_buf.length; 1061 ibr.idx = 0; 1062 1063 gss_release_buffer(&min_stat, &msg_buf); 1064 } else { 1065 ibr.idx = 0; 1066 ibr.clen = 0; 1067 return (EOF); 1068 } 1069 } 1070 1071 /* 1072 * If there are 'nbytes' of plain text available, use them, else 1073 * get whats available. 1074 */ 1075 nbytes = (nbytes < (ibr.clen - ibr.idx) ? nbytes : ibr.clen - ibr.idx); 1076 1077 memcpy(buf, ibr.buf + ibr.idx, nbytes); 1078 ibr.idx += nbytes; 1079 1080 return ((nbytes == 0 ? EOF : nbytes)); 1081 } 1082 1083 /* 1084 * Get a buffer of 'maxlen' bytes from the client. 1085 * If we are using GSSAPI protection, use the secure 1086 * input buffer. 1087 */ 1088 int 1089 sec_read(int fd, char *buf, int maxlen) 1090 { 1091 int nbytes = 0; 1092 1093 if (gss_info.data_prot != PROT_C && 1094 IS_GSSAUTH(cur_auth_type) && 1095 (gss_info.authstate & GSS_ADAT_DONE)) { 1096 /* Get as much data as possible */ 1097 nbytes = sec_getbytes(fd, buf, maxlen); 1098 if (nbytes == EOF) 1099 nbytes = 0; 1100 } else { 1101 nbytes = read(fd, buf, maxlen); 1102 } 1103 return (nbytes); 1104 } 1105 1106 /* 1107 * sec_getc 1108 * 1109 * Get a single character from the secure network buffer. 1110 */ 1111 int 1112 sec_getc(FILE *stream) 1113 { 1114 int nbytes; 1115 unsigned char c; 1116 1117 if (gss_info.data_prot != PROT_C && 1118 IS_GSSAUTH(cur_auth_type) && 1119 (gss_info.authstate & GSS_ADAT_DONE)) { 1120 nbytes = sec_getbytes(fileno(stream), (char *)&c, 1); 1121 if (nbytes > 0) 1122 nbytes = (int)c; 1123 return (nbytes); 1124 } else 1125 return (getc(stream)); 1126 } 1127 1128 /* 1129 * sec_reply 1130 * 1131 * Securely encode a reply destined for the ftp client 1132 * depending on the GSSAPI settings. 1133 */ 1134 int 1135 sec_reply(char *buf, int bufsiz, int n) 1136 { 1137 char *out = NULL, *in = NULL; 1138 size_t inlen; 1139 gss_buffer_desc in_buf, out_buf; 1140 OM_uint32 maj_stat, min_stat; 1141 int conf_state, length, kerror; 1142 int ret = 0; 1143 1144 if (debug) 1145 syslog(LOG_DEBUG, "encoding %s", buf); 1146 1147 in_buf.value = buf; 1148 in_buf.length = strlen(buf) + 1; 1149 maj_stat = gss_wrap(&min_stat, gss_info.context, 1150 gss_info.ctrl_prot == PROT_P, 1151 GSS_C_QOP_DEFAULT, 1152 &in_buf, &conf_state, 1153 &out_buf); 1154 if (maj_stat != GSS_S_COMPLETE) { 1155 syslog(LOG_ERR, "gss_wrap %s did not complete", 1156 (gss_info.ctrl_prot == PROT_P) ? "ENC": "MIC"); 1157 ret = -2; 1158 gss_release_buffer(&min_stat, &out_buf); 1159 goto end; 1160 } else if ((gss_info.ctrl_prot == PROT_P) && !conf_state) { 1161 syslog(LOG_ERR, "gss_wrap did not encrypt message"); 1162 ret = -2; 1163 gss_release_buffer(&min_stat, &out_buf); 1164 goto end; 1165 } else { 1166 out = (char *)malloc(out_buf.length); 1167 if (out == NULL) { 1168 syslog(LOG_ERR, "Memory error allocating buffer"); 1169 ret = -2; 1170 gss_release_buffer(&min_stat, &out_buf); 1171 goto end; 1172 } 1173 memcpy(out, out_buf.value, out_buf.length); 1174 length = out_buf.length; 1175 gss_release_buffer(&min_stat, &out_buf); 1176 ret = 0; 1177 } 1178 /* 1179 * Base64 encode the reply. encrypted "out" becomes 1180 * encoded "in" buffer. 1181 * Stick it all back in 'buf' for final output. 1182 */ 1183 inlen = ENCODELEN(length); 1184 in = (char *)malloc(inlen); 1185 if (in == NULL) { 1186 syslog(LOG_ERR, "Memory error allocating buffer"); 1187 ret = -2; 1188 goto end; 1189 } 1190 if ((kerror = radix_encode((unsigned char *)out, 1191 (unsigned char *)in, inlen, 1192 &length, 0))) { 1193 syslog(LOG_ERR, "Couldn't encode reply(%s)", 1194 radix_error(kerror)); 1195 strncpy(buf, in, bufsiz-1); 1196 buf[bufsiz - 1] = '\0'; 1197 } else { 1198 snprintf(buf, bufsiz, "%s%c%s", 1199 gss_info.ctrl_prot == PROT_P ? "632" : "631", 1200 n ? ' ' : '-', in); 1201 } 1202 end: 1203 if (in) free(in); 1204 if (out) free(out); 1205 1206 return (ret); 1207 } 1208 1209 /* 1210 * sec_decode_command 1211 * 1212 * If a command is received which is encoded(ENC, MIC, or CONF), 1213 * decode it here using GSSAPI. 1214 */ 1215 char * 1216 sec_decode_command(char *cmd) 1217 { 1218 char *out = NULL, *cp; 1219 int len, mic, outlen; 1220 gss_buffer_desc xmit_buf, msg_buf; 1221 OM_uint32 maj_stat, min_stat; 1222 int conf_state; 1223 int kerror; 1224 char *cs; 1225 char *s = cmd; 1226 1227 if ((cs = strpbrk(s, " \r\n"))) 1228 *cs++ = '\0'; 1229 upper(s); 1230 1231 if ((mic = strcmp(s, "ENC")) != 0 && strcmp(s, "MIC") && 1232 strcmp(s, "CONF")) { 1233 reply(533, "All commands must be protected."); 1234 syslog(LOG_ERR, "Unprotected command received %s", s); 1235 *s = '\0'; 1236 return (s); 1237 } 1238 1239 if ((cp = strpbrk(cs, " \r\n"))) 1240 *cp = '\0'; 1241 1242 outlen = DECODELEN(strlen(cs)); 1243 1244 out = (char *)malloc(outlen); 1245 if (out == NULL) { 1246 reply(501, "Cannot decode response - not enough memory"); 1247 syslog(LOG_ERR, "Cannot decode response - not enough memory"); 1248 *s = '\0'; 1249 return (s); 1250 } 1251 len = strlen(cs); 1252 if ((kerror = radix_encode((unsigned char *)cs, 1253 (unsigned char *)out, 1254 outlen, &len, 1))) { 1255 reply(501, "Can't base 64 decode argument to %s command(%s)", 1256 mic ? "MIC" : "ENC", radix_error(kerror)); 1257 *s = '\0'; 1258 free(out); 1259 return (s); 1260 } 1261 1262 if (debug) 1263 syslog(LOG_DEBUG, "getline got %d from %s <%s >\n", 1264 len, cs, mic ? "MIC" : "ENC"); 1265 1266 xmit_buf.value = out; 1267 xmit_buf.length = len; 1268 1269 /* decrypt the message */ 1270 conf_state = !mic; 1271 maj_stat = gss_unwrap(&min_stat, gss_info.context, &xmit_buf, 1272 &msg_buf, &conf_state, NULL); 1273 if (maj_stat == GSS_S_CONTINUE_NEEDED) { 1274 if (debug) syslog(LOG_DEBUG, "%s-unwrap continued", 1275 mic ? "MIC" : "ENC"); 1276 reply(535, "%s-unwrap continued, oops", mic ? "MIC" : "ENC"); 1277 *s = 0; 1278 free(out); 1279 return (s); 1280 } 1281 1282 free(out); 1283 if (maj_stat != GSS_S_COMPLETE) { 1284 reply_gss_error(535, maj_stat, min_stat, 1285 gss_info.mechoid, 1286 mic ? "failed unwrapping MIC message": 1287 "failed unwrapping ENC message"); 1288 *s = 0; 1289 return (s); 1290 } 1291 1292 memcpy(s, msg_buf.value, msg_buf.length); 1293 strcpy(s + msg_buf.length-(s[msg_buf.length-1] ? 0 : 1), "\r\n"); 1294 gss_release_buffer(&min_stat, &msg_buf); 1295 1296 return (s); 1297 } 1298 1299 #endif /* defined(USE_GSS) */