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