1 /* 2 * Copyright (c) 1999-2004 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11 #include <sm/gen.h> 12 SM_RCSID("@(#)$Id: sfsasl.c,v 8.101 2004/12/15 22:45:55 ca Exp $") 13 #include <stdlib.h> 14 #include <sendmail.h> 15 #include <errno.h> 16 17 /* allow to disable error handling code just in case... */ 18 #ifndef DEAL_WITH_ERROR_SSL 19 # define DEAL_WITH_ERROR_SSL 1 20 #endif /* ! DEAL_WITH_ERROR_SSL */ 21 22 #if SASL 23 # include "sfsasl.h" 24 25 /* Structure used by the "sasl" file type */ 26 struct sasl_obj 27 { 28 SM_FILE_T *fp; 29 sasl_conn_t *conn; 30 }; 31 32 struct sasl_info 33 { 34 SM_FILE_T *fp; 35 sasl_conn_t *conn; 36 }; 37 38 /* 39 ** SASL_GETINFO - returns requested information about a "sasl" file 40 ** descriptor. 41 ** 42 ** Parameters: 43 ** fp -- the file descriptor 44 ** what -- the type of information requested 45 ** valp -- the thang to return the information in 46 ** 47 ** Returns: 48 ** -1 for unknown requests 49 ** >=0 on success with valp filled in (if possible). 50 */ 51 52 static int sasl_getinfo __P((SM_FILE_T *, int, void *)); 53 54 static int 55 sasl_getinfo(fp, what, valp) 56 SM_FILE_T *fp; 57 int what; 58 void *valp; 59 { 60 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; 61 62 switch (what) 63 { 64 case SM_IO_WHAT_FD: 65 if (so->fp == NULL) 66 return -1; 67 return so->fp->f_file; /* for stdio fileno() compatability */ 68 69 case SM_IO_IS_READABLE: 70 if (so->fp == NULL) 71 return 0; 72 73 /* get info from underlying file */ 74 return sm_io_getinfo(so->fp, what, valp); 75 76 default: 77 return -1; 78 } 79 } 80 81 /* 82 ** SASL_OPEN -- creates the sasl specific information for opening a 83 ** file of the sasl type. 84 ** 85 ** Parameters: 86 ** fp -- the file pointer associated with the new open 87 ** info -- contains the sasl connection information pointer and 88 ** the original SM_FILE_T that holds the open 89 ** flags -- ignored 90 ** rpool -- ignored 91 ** 92 ** Returns: 93 ** 0 on success 94 */ 95 96 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *)); 97 98 /* ARGSUSED2 */ 99 static int 100 sasl_open(fp, info, flags, rpool) 101 SM_FILE_T *fp; 102 const void *info; 103 int flags; 104 const void *rpool; 105 { 106 struct sasl_obj *so; 107 struct sasl_info *si = (struct sasl_info *) info; 108 109 so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj)); 110 if (so == NULL) 111 { 112 errno = ENOMEM; 113 return -1; 114 } 115 so->fp = si->fp; 116 so->conn = si->conn; 117 118 /* 119 ** The underlying 'fp' is set to SM_IO_NOW so that the entire 120 ** encoded string is written in one chunk. Otherwise there is 121 ** the possibility that it may appear illegal, bogus or 122 ** mangled to the other side of the connection. 123 ** We will read or write through 'fp' since it is the opaque 124 ** connection for the communications. We need to treat it this 125 ** way in case the encoded string is to be sent down a TLS 126 ** connection rather than, say, sm_io's stdio. 127 */ 128 129 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0); 130 fp->f_cookie = so; 131 return 0; 132 } 133 134 /* 135 ** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer 136 ** 137 ** Parameters: 138 ** fp -- the file pointer to close 139 ** 140 ** Returns: 141 ** 0 on success 142 */ 143 144 static int sasl_close __P((SM_FILE_T *)); 145 146 static int 147 sasl_close(fp) 148 SM_FILE_T *fp; 149 { 150 struct sasl_obj *so; 151 152 so = (struct sasl_obj *) fp->f_cookie; 153 if (so == NULL) 154 return 0; 155 if (so->fp != NULL) 156 { 157 sm_io_close(so->fp, SM_TIME_DEFAULT); 158 so->fp = NULL; 159 } 160 sm_free(so); 161 so = NULL; 162 return 0; 163 } 164 165 /* how to deallocate a buffer allocated by SASL */ 166 extern void sm_sasl_free __P((void *)); 167 # define SASL_DEALLOC(b) sm_sasl_free(b) 168 169 /* 170 ** SASL_READ -- read encrypted information and decrypt it for the caller 171 ** 172 ** Parameters: 173 ** fp -- the file pointer 174 ** buf -- the location to place the decrypted information 175 ** size -- the number of bytes to read after decryption 176 ** 177 ** Results: 178 ** -1 on error 179 ** otherwise the number of bytes read 180 */ 181 182 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t)); 183 184 static ssize_t 185 sasl_read(fp, buf, size) 186 SM_FILE_T *fp; 187 char *buf; 188 size_t size; 189 { 190 int result; 191 ssize_t len; 192 # if SASL >= 20000 193 static const char *outbuf = NULL; 194 # else /* SASL >= 20000 */ 195 static char *outbuf = NULL; 196 # endif /* SASL >= 20000 */ 197 static unsigned int outlen = 0; 198 static unsigned int offset = 0; 199 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; 200 201 /* 202 ** sasl_decode() may require more data than a single read() returns. 203 ** Hence we have to put a loop around the decoding. 204 ** This also requires that we may have to split up the returned 205 ** data since it might be larger than the allowed size. 206 ** Therefore we use a static pointer and return portions of it 207 ** if necessary. 208 ** XXX Note: This function is not thread-safe nor can it be used 209 ** on more than one file. A correct implementation would store 210 ** this data in fp->f_cookie. 211 */ 212 213 # if SASL >= 20000 214 while (outlen == 0) 215 # else /* SASL >= 20000 */ 216 while (outbuf == NULL && outlen == 0) 217 # endif /* SASL >= 20000 */ 218 { 219 len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size); 220 if (len <= 0) 221 return len; 222 result = sasl_decode(so->conn, buf, 223 (unsigned int) len, &outbuf, &outlen); 224 if (result != SASL_OK) 225 { 226 outbuf = NULL; 227 offset = 0; 228 outlen = 0; 229 return -1; 230 } 231 } 232 233 if (outbuf == NULL) 234 { 235 /* be paranoid: outbuf == NULL but outlen != 0 */ 236 syserr("@sasl_read failure: outbuf == NULL but outlen != 0"); 237 /* NOTREACHED */ 238 } 239 if (outlen - offset > size) 240 { 241 /* return another part of the buffer */ 242 (void) memcpy(buf, outbuf + offset, size); 243 offset += size; 244 len = size; 245 } 246 else 247 { 248 /* return the rest of the buffer */ 249 len = outlen - offset; 250 (void) memcpy(buf, outbuf + offset, (size_t) len); 251 # if SASL < 20000 252 SASL_DEALLOC(outbuf); 253 # endif /* SASL < 20000 */ 254 outbuf = NULL; 255 offset = 0; 256 outlen = 0; 257 } 258 return len; 259 } 260 261 /* 262 ** SASL_WRITE -- write information out after encrypting it 263 ** 264 ** Parameters: 265 ** fp -- the file pointer 266 ** buf -- holds the data to be encrypted and written 267 ** size -- the number of bytes to have encrypted and written 268 ** 269 ** Returns: 270 ** -1 on error 271 ** otherwise number of bytes written 272 */ 273 274 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t)); 275 276 static ssize_t 277 sasl_write(fp, buf, size) 278 SM_FILE_T *fp; 279 const char *buf; 280 size_t size; 281 { 282 int result; 283 # if SASL >= 20000 284 const char *outbuf; 285 # else /* SASL >= 20000 */ 286 char *outbuf; 287 # endif /* SASL >= 20000 */ 288 unsigned int outlen, *maxencode; 289 size_t ret = 0, total = 0; 290 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie; 291 292 /* 293 ** Fetch the maximum input buffer size for sasl_encode(). 294 ** This can be less than the size set in attemptauth() 295 ** due to a negotation with the other side, e.g., 296 ** Cyrus IMAP lmtp program sets maxbuf=4096, 297 ** digestmd5 substracts 25 and hence we'll get 4071 298 ** instead of 8192 (MAXOUTLEN). 299 ** Hack (for now): simply reduce the size, callers are (must be) 300 ** able to deal with that and invoke sasl_write() again with 301 ** the rest of the data. 302 ** Note: it would be better to store this value in the context 303 ** after the negotiation. 304 */ 305 306 result = sasl_getprop(so->conn, SASL_MAXOUTBUF, 307 (const void **) &maxencode); 308 if (result == SASL_OK && size > *maxencode && *maxencode > 0) 309 size = *maxencode; 310 311 result = sasl_encode(so->conn, buf, 312 (unsigned int) size, &outbuf, &outlen); 313 314 if (result != SASL_OK) 315 return -1; 316 317 if (outbuf != NULL) 318 { 319 while (outlen > 0) 320 { 321 /* XXX result == 0? */ 322 ret = sm_io_write(so->fp, SM_TIME_DEFAULT, 323 &outbuf[total], outlen); 324 if (ret <= 0) 325 return ret; 326 outlen -= ret; 327 total += ret; 328 } 329 # if SASL < 20000 330 SASL_DEALLOC(outbuf); 331 # endif /* SASL < 20000 */ 332 } 333 return size; 334 } 335 336 /* 337 ** SFDCSASL -- create sasl file type and open in and out file pointers 338 ** for sendmail to read from and write to. 339 ** 340 ** Parameters: 341 ** fin -- the sm_io file encrypted data to be read from 342 ** fout -- the sm_io file encrypted data to be writen to 343 ** conn -- the sasl connection pointer 344 ** 345 ** Returns: 346 ** -1 on error 347 ** 0 on success 348 ** 349 ** Side effects: 350 ** The arguments "fin" and "fout" are replaced with the new 351 ** SM_FILE_T pointers. 352 */ 353 354 int 355 sfdcsasl(fin, fout, conn) 356 SM_FILE_T **fin; 357 SM_FILE_T **fout; 358 sasl_conn_t *conn; 359 { 360 SM_FILE_T *newin, *newout; 361 SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, 362 sasl_read, sasl_write, NULL, sasl_getinfo, NULL, 363 SM_TIME_FOREVER); 364 struct sasl_info info; 365 366 if (conn == NULL) 367 { 368 /* no need to do anything */ 369 return 0; 370 } 371 372 SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, 373 sasl_read, sasl_write, NULL, sasl_getinfo, NULL, 374 SM_TIME_FOREVER); 375 info.fp = *fin; 376 info.conn = conn; 377 newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, 378 SM_IO_RDONLY_B, NULL); 379 380 if (newin == NULL) 381 return -1; 382 383 info.fp = *fout; 384 info.conn = conn; 385 newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, 386 SM_IO_WRONLY_B, NULL); 387 388 if (newout == NULL) 389 { 390 (void) sm_io_close(newin, SM_TIME_DEFAULT); 391 return -1; 392 } 393 sm_io_automode(newin, newout); 394 395 *fin = newin; 396 *fout = newout; 397 return 0; 398 } 399 #endif /* SASL */ 400 401 #if STARTTLS 402 # include "sfsasl.h" 403 # include <openssl/err.h> 404 405 /* Structure used by the "tls" file type */ 406 struct tls_obj 407 { 408 SM_FILE_T *fp; 409 SSL *con; 410 }; 411 412 struct tls_info 413 { 414 SM_FILE_T *fp; 415 SSL *con; 416 }; 417 418 /* 419 ** TLS_GETINFO - returns requested information about a "tls" file 420 ** descriptor. 421 ** 422 ** Parameters: 423 ** fp -- the file descriptor 424 ** what -- the type of information requested 425 ** valp -- the thang to return the information in (unused) 426 ** 427 ** Returns: 428 ** -1 for unknown requests 429 ** >=0 on success with valp filled in (if possible). 430 */ 431 432 static int tls_getinfo __P((SM_FILE_T *, int, void *)); 433 434 /* ARGSUSED2 */ 435 static int 436 tls_getinfo(fp, what, valp) 437 SM_FILE_T *fp; 438 int what; 439 void *valp; 440 { 441 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 442 443 switch (what) 444 { 445 case SM_IO_WHAT_FD: 446 if (so->fp == NULL) 447 return -1; 448 return so->fp->f_file; /* for stdio fileno() compatability */ 449 450 case SM_IO_IS_READABLE: 451 return SSL_pending(so->con) > 0; 452 453 default: 454 return -1; 455 } 456 } 457 458 /* 459 ** TLS_OPEN -- creates the tls specific information for opening a 460 ** file of the tls type. 461 ** 462 ** Parameters: 463 ** fp -- the file pointer associated with the new open 464 ** info -- the sm_io file pointer holding the open and the 465 ** TLS encryption connection to be read from or written to 466 ** flags -- ignored 467 ** rpool -- ignored 468 ** 469 ** Returns: 470 ** 0 on success 471 */ 472 473 static int tls_open __P((SM_FILE_T *, const void *, int, const void *)); 474 475 /* ARGSUSED2 */ 476 static int 477 tls_open(fp, info, flags, rpool) 478 SM_FILE_T *fp; 479 const void *info; 480 int flags; 481 const void *rpool; 482 { 483 struct tls_obj *so; 484 struct tls_info *ti = (struct tls_info *) info; 485 486 so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj)); 487 if (so == NULL) 488 { 489 errno = ENOMEM; 490 return -1; 491 } 492 so->fp = ti->fp; 493 so->con = ti->con; 494 495 /* 496 ** We try to get the "raw" file descriptor that TLS uses to 497 ** do the actual read/write with. This is to allow us control 498 ** over the file descriptor being a blocking or non-blocking type. 499 ** Under the covers TLS handles the change and this allows us 500 ** to do timeouts with sm_io. 501 */ 502 503 fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL); 504 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0); 505 fp->f_cookie = so; 506 return 0; 507 } 508 509 /* 510 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer 511 ** 512 ** Parameters: 513 ** fp -- the file pointer to close 514 ** 515 ** Returns: 516 ** 0 on success 517 */ 518 519 static int tls_close __P((SM_FILE_T *)); 520 521 static int 522 tls_close(fp) 523 SM_FILE_T *fp; 524 { 525 struct tls_obj *so; 526 527 so = (struct tls_obj *) fp->f_cookie; 528 if (so == NULL) 529 return 0; 530 if (so->fp != NULL) 531 { 532 sm_io_close(so->fp, SM_TIME_DEFAULT); 533 so->fp = NULL; 534 } 535 sm_free(so); 536 so = NULL; 537 return 0; 538 } 539 540 /* maximum number of retries for TLS related I/O due to handshakes */ 541 # define MAX_TLS_IOS 4 542 543 /* 544 ** TLS_READ -- read secured information for the caller 545 ** 546 ** Parameters: 547 ** fp -- the file pointer 548 ** buf -- the location to place the data 549 ** size -- the number of bytes to read from connection 550 ** 551 ** Results: 552 ** -1 on error 553 ** otherwise the number of bytes read 554 */ 555 556 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t)); 557 558 static ssize_t 559 tls_read(fp, buf, size) 560 SM_FILE_T *fp; 561 char *buf; 562 size_t size; 563 { 564 int r; 565 static int again = MAX_TLS_IOS; 566 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 567 char *err; 568 569 r = SSL_read(so->con, (char *) buf, size); 570 571 if (r > 0) 572 { 573 again = MAX_TLS_IOS; 574 return r; 575 } 576 577 err = NULL; 578 switch (SSL_get_error(so->con, r)) 579 { 580 case SSL_ERROR_NONE: 581 case SSL_ERROR_ZERO_RETURN: 582 again = MAX_TLS_IOS; 583 break; 584 case SSL_ERROR_WANT_WRITE: 585 if (--again <= 0) 586 err = "read W BLOCK"; 587 else 588 errno = EAGAIN; 589 break; 590 case SSL_ERROR_WANT_READ: 591 if (--again <= 0) 592 err = "read R BLOCK"; 593 else 594 errno = EAGAIN; 595 break; 596 case SSL_ERROR_WANT_X509_LOOKUP: 597 err = "write X BLOCK"; 598 break; 599 case SSL_ERROR_SYSCALL: 600 if (r == 0 && errno == 0) /* out of protocol EOF found */ 601 break; 602 err = "syscall error"; 603 /* 604 get_last_socket_error()); 605 */ 606 break; 607 case SSL_ERROR_SSL: 608 #if DEAL_WITH_ERROR_SSL 609 if (r == 0 && errno == 0) /* out of protocol EOF found */ 610 break; 611 #endif /* DEAL_WITH_ERROR_SSL */ 612 err = "generic SSL error"; 613 if (LogLevel > 9) 614 tlslogerr("read"); 615 616 #if DEAL_WITH_ERROR_SSL 617 /* avoid repeated calls? */ 618 if (r == 0) 619 r = -1; 620 #endif /* DEAL_WITH_ERROR_SSL */ 621 break; 622 } 623 if (err != NULL) 624 { 625 int save_errno; 626 627 save_errno = (errno == 0) ? EIO : errno; 628 again = MAX_TLS_IOS; 629 if (LogLevel > 9) 630 sm_syslog(LOG_WARNING, NOQID, 631 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s", 632 err, r, errno, 633 ERR_error_string(ERR_get_error(), NULL)); 634 else if (LogLevel > 7) 635 sm_syslog(LOG_WARNING, NOQID, 636 "STARTTLS: read error=%s (%d)", err, r); 637 errno = save_errno; 638 } 639 return r; 640 } 641 642 /* 643 ** TLS_WRITE -- write information out through secure connection 644 ** 645 ** Parameters: 646 ** fp -- the file pointer 647 ** buf -- holds the data to be securely written 648 ** size -- the number of bytes to write 649 ** 650 ** Returns: 651 ** -1 on error 652 ** otherwise number of bytes written 653 */ 654 655 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t)); 656 657 static ssize_t 658 tls_write(fp, buf, size) 659 SM_FILE_T *fp; 660 const char *buf; 661 size_t size; 662 { 663 int r; 664 static int again = MAX_TLS_IOS; 665 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 666 char *err; 667 668 r = SSL_write(so->con, (char *) buf, size); 669 670 if (r > 0) 671 { 672 again = MAX_TLS_IOS; 673 return r; 674 } 675 err = NULL; 676 switch (SSL_get_error(so->con, r)) 677 { 678 case SSL_ERROR_NONE: 679 case SSL_ERROR_ZERO_RETURN: 680 again = MAX_TLS_IOS; 681 break; 682 case SSL_ERROR_WANT_WRITE: 683 if (--again <= 0) 684 err = "write W BLOCK"; 685 else 686 errno = EAGAIN; 687 break; 688 case SSL_ERROR_WANT_READ: 689 if (--again <= 0) 690 err = "write R BLOCK"; 691 else 692 errno = EAGAIN; 693 break; 694 case SSL_ERROR_WANT_X509_LOOKUP: 695 err = "write X BLOCK"; 696 break; 697 case SSL_ERROR_SYSCALL: 698 if (r == 0 && errno == 0) /* out of protocol EOF found */ 699 break; 700 err = "syscall error"; 701 /* 702 get_last_socket_error()); 703 */ 704 break; 705 case SSL_ERROR_SSL: 706 err = "generic SSL error"; 707 /* 708 ERR_GET_REASON(ERR_peek_error())); 709 */ 710 if (LogLevel > 9) 711 tlslogerr("write"); 712 713 #if DEAL_WITH_ERROR_SSL 714 /* avoid repeated calls? */ 715 if (r == 0) 716 r = -1; 717 #endif /* DEAL_WITH_ERROR_SSL */ 718 break; 719 } 720 if (err != NULL) 721 { 722 int save_errno; 723 724 save_errno = (errno == 0) ? EIO : errno; 725 again = MAX_TLS_IOS; 726 if (LogLevel > 9) 727 sm_syslog(LOG_WARNING, NOQID, 728 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s", 729 err, r, errno, 730 ERR_error_string(ERR_get_error(), NULL)); 731 else if (LogLevel > 7) 732 sm_syslog(LOG_WARNING, NOQID, 733 "STARTTLS: write error=%s (%d)", err, r); 734 errno = save_errno; 735 } 736 return r; 737 } 738 739 /* 740 ** SFDCTLS -- create tls file type and open in and out file pointers 741 ** for sendmail to read from and write to. 742 ** 743 ** Parameters: 744 ** fin -- data input source being replaced 745 ** fout -- data output source being replaced 746 ** con -- the tls connection pointer 747 ** 748 ** Returns: 749 ** -1 on error 750 ** 0 on success 751 ** 752 ** Side effects: 753 ** The arguments "fin" and "fout" are replaced with the new 754 ** SM_FILE_T pointers. 755 ** The original "fin" and "fout" are preserved in the tls file 756 ** type but are not actually used because of the design of TLS. 757 */ 758 759 int 760 sfdctls(fin, fout, con) 761 SM_FILE_T **fin; 762 SM_FILE_T **fout; 763 SSL *con; 764 { 765 SM_FILE_T *tlsin, *tlsout; 766 SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close, 767 tls_read, tls_write, NULL, tls_getinfo, NULL, 768 SM_TIME_FOREVER); 769 struct tls_info info; 770 771 SM_ASSERT(con != NULL); 772 773 SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close, 774 tls_read, tls_write, NULL, tls_getinfo, NULL, 775 SM_TIME_FOREVER); 776 info.fp = *fin; 777 info.con = con; 778 tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B, 779 NULL); 780 if (tlsin == NULL) 781 return -1; 782 783 info.fp = *fout; 784 tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B, 785 NULL); 786 if (tlsout == NULL) 787 { 788 (void) sm_io_close(tlsin, SM_TIME_DEFAULT); 789 return -1; 790 } 791 sm_io_automode(tlsin, tlsout); 792 793 *fin = tlsin; 794 *fout = tlsout; 795 return 0; 796 } 797 #endif /* STARTTLS */ 798