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