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