1 /* 2 * Copyright (c) 1999-2001 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.86 2001/09/11 04:05:16 gshapiro 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 ret = sm_io_write(so->fp, SM_TIME_DEFAULT, 274 &outbuf[total], outlen); 275 outlen -= ret; 276 total += ret; 277 } 278 SASL_DEALLOC(outbuf); 279 } 280 return size; 281 } 282 283 /* 284 ** SFDCSASL -- create sasl file type and open in and out file pointers 285 ** for sendmail to read from and write to. 286 ** 287 ** Parameters: 288 ** fin -- the sm_io file encrypted data to be read from 289 ** fout -- the sm_io file encrypted data to be writen to 290 ** conn -- the sasl connection pointer 291 ** 292 ** Returns: 293 ** -1 on error 294 ** 0 on success 295 ** 296 ** Side effects: 297 ** The arguments "fin" and "fout" are replaced with the new 298 ** SM_FILE_T pointers. 299 */ 300 301 int 302 sfdcsasl(fin, fout, conn) 303 SM_FILE_T **fin; 304 SM_FILE_T **fout; 305 sasl_conn_t *conn; 306 { 307 SM_FILE_T *newin, *newout; 308 SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, 309 sasl_read, sasl_write, NULL, sasl_getinfo, NULL, 310 SM_TIME_FOREVER); 311 struct sasl_info info; 312 313 if (conn == NULL) 314 { 315 /* no need to do anything */ 316 return 0; 317 } 318 319 SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close, 320 sasl_read, sasl_write, NULL, sasl_getinfo, NULL, 321 SM_TIME_FOREVER); 322 info.fp = *fin; 323 info.conn = conn; 324 newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY, 325 NULL); 326 327 if (newin == NULL) 328 return -1; 329 330 info.fp = *fout; 331 info.conn = conn; 332 newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY, 333 NULL); 334 335 if (newout == NULL) 336 { 337 (void) sm_io_close(newin, SM_TIME_DEFAULT); 338 return -1; 339 } 340 sm_io_automode(newin, newout); 341 342 *fin = newin; 343 *fout = newout; 344 return 0; 345 } 346 #endif /* SASL */ 347 348 #if STARTTLS 349 # include "sfsasl.h" 350 # include <openssl/err.h> 351 352 /* Structure used by the "tls" file type */ 353 struct tls_obj 354 { 355 SM_FILE_T *fp; 356 SSL *con; 357 }; 358 359 struct tls_info 360 { 361 SM_FILE_T *fp; 362 SSL *con; 363 }; 364 365 /* 366 ** TLS_GETINFO - returns requested information about a "tls" file 367 ** descriptor. 368 ** 369 ** Parameters: 370 ** fp -- the file descriptor 371 ** what -- the type of information requested 372 ** valp -- the thang to return the information in (unused) 373 ** 374 ** Returns: 375 ** -1 for unknown requests 376 ** >=0 on success with valp filled in (if possible). 377 */ 378 379 static int tls_getinfo __P((SM_FILE_T *, int, void *)); 380 381 /* ARGSUSED2 */ 382 static int 383 tls_getinfo(fp, what, valp) 384 SM_FILE_T *fp; 385 int what; 386 void *valp; 387 { 388 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 389 390 switch (what) 391 { 392 case SM_IO_WHAT_FD: 393 if (so->fp == NULL) 394 return -1; 395 return so->fp->f_file; /* for stdio fileno() compatability */ 396 397 case SM_IO_IS_READABLE: 398 return SSL_pending(so->con) > 0; 399 400 default: 401 return -1; 402 } 403 } 404 405 /* 406 ** TLS_OPEN -- creates the tls specific information for opening a 407 ** file of the tls type. 408 ** 409 ** Parameters: 410 ** fp -- the file pointer associated with the new open 411 ** info -- the sm_io file pointer holding the open and the 412 ** TLS encryption connection to be read from or written to 413 ** flags -- ignored 414 ** rpool -- ignored 415 ** 416 ** Returns: 417 ** 0 on success 418 */ 419 420 static int tls_open __P((SM_FILE_T *, const void *, int, const void *)); 421 422 /* ARGSUSED2 */ 423 static int 424 tls_open(fp, info, flags, rpool) 425 SM_FILE_T *fp; 426 const void *info; 427 int flags; 428 const void *rpool; 429 { 430 struct tls_obj *so; 431 struct tls_info *ti = (struct tls_info *) info; 432 433 so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj)); 434 so->fp = ti->fp; 435 so->con = ti->con; 436 437 /* 438 ** We try to get the "raw" file descriptor that TLS uses to 439 ** do the actual read/write with. This is to allow us control 440 ** over the file descriptor being a blocking or non-blocking type. 441 ** Under the covers TLS handles the change and this allows us 442 ** to do timeouts with sm_io. 443 */ 444 445 fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL); 446 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0); 447 fp->f_cookie = so; 448 return 0; 449 } 450 451 /* 452 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer 453 ** 454 ** Parameters: 455 ** fp -- the file pointer to close 456 ** 457 ** Returns: 458 ** 0 on success 459 */ 460 461 static int tls_close __P((SM_FILE_T *)); 462 463 static int 464 tls_close(fp) 465 SM_FILE_T *fp; 466 { 467 struct tls_obj *so; 468 469 so = (struct tls_obj *) fp->f_cookie; 470 if (so->fp != NULL) 471 { 472 sm_io_close(so->fp, SM_TIME_DEFAULT); 473 so->fp = NULL; 474 } 475 sm_free(so); 476 so = NULL; 477 return 0; 478 } 479 480 /* maximum number of retries for TLS related I/O due to handshakes */ 481 # define MAX_TLS_IOS 4 482 483 /* 484 ** TLS_READ -- read secured information for the caller 485 ** 486 ** Parameters: 487 ** fp -- the file pointer 488 ** buf -- the location to place the data 489 ** size -- the number of bytes to read from connection 490 ** 491 ** Results: 492 ** -1 on error 493 ** otherwise the number of bytes read 494 */ 495 496 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t)); 497 498 static ssize_t 499 tls_read(fp, buf, size) 500 SM_FILE_T *fp; 501 char *buf; 502 size_t size; 503 { 504 int r; 505 static int again = MAX_TLS_IOS; 506 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 507 char *err; 508 509 r = SSL_read(so->con, (char *) buf, size); 510 511 if (r > 0) 512 { 513 again = MAX_TLS_IOS; 514 return r; 515 } 516 517 err = NULL; 518 switch (SSL_get_error(so->con, r)) 519 { 520 case SSL_ERROR_NONE: 521 case SSL_ERROR_ZERO_RETURN: 522 again = MAX_TLS_IOS; 523 break; 524 case SSL_ERROR_WANT_WRITE: 525 if (--again <= 0) 526 err = "read W BLOCK"; 527 else 528 errno = EAGAIN; 529 break; 530 case SSL_ERROR_WANT_READ: 531 if (--again <= 0) 532 err = "read R BLOCK"; 533 else 534 errno = EAGAIN; 535 break; 536 case SSL_ERROR_WANT_X509_LOOKUP: 537 err = "write X BLOCK"; 538 break; 539 case SSL_ERROR_SYSCALL: 540 if (r == 0 && errno == 0) /* out of protocol EOF found */ 541 break; 542 err = "syscall error"; 543 /* 544 get_last_socket_error()); 545 */ 546 break; 547 case SSL_ERROR_SSL: 548 err = "generic SSL error"; 549 if (LogLevel > 9) 550 tlslogerr("read"); 551 break; 552 } 553 if (err != NULL) 554 { 555 again = MAX_TLS_IOS; 556 if (errno == 0) 557 errno = EIO; 558 if (LogLevel > 7) 559 sm_syslog(LOG_WARNING, NOQID, 560 "STARTTLS: read error=%s (%d)", err, r); 561 } 562 return r; 563 } 564 565 /* 566 ** TLS_WRITE -- write information out through secure connection 567 ** 568 ** Parameters: 569 ** fp -- the file pointer 570 ** buf -- holds the data to be securely written 571 ** size -- the number of bytes to write 572 ** 573 ** Returns: 574 ** -1 on error 575 ** otherwise number of bytes written 576 */ 577 578 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t)); 579 580 static ssize_t 581 tls_write(fp, buf, size) 582 SM_FILE_T *fp; 583 const char *buf; 584 size_t size; 585 { 586 int r; 587 static int again = MAX_TLS_IOS; 588 struct tls_obj *so = (struct tls_obj *) fp->f_cookie; 589 char *err; 590 591 r = SSL_write(so->con, (char *) buf, size); 592 593 if (r > 0) 594 { 595 again = MAX_TLS_IOS; 596 return r; 597 } 598 err = NULL; 599 switch (SSL_get_error(so->con, r)) 600 { 601 case SSL_ERROR_NONE: 602 case SSL_ERROR_ZERO_RETURN: 603 again = MAX_TLS_IOS; 604 break; 605 case SSL_ERROR_WANT_WRITE: 606 if (--again <= 0) 607 err = "write W BLOCK"; 608 else 609 errno = EAGAIN; 610 break; 611 case SSL_ERROR_WANT_READ: 612 if (--again <= 0) 613 err = "write R BLOCK"; 614 else 615 errno = EAGAIN; 616 break; 617 case SSL_ERROR_WANT_X509_LOOKUP: 618 err = "write X BLOCK"; 619 break; 620 case SSL_ERROR_SYSCALL: 621 if (r == 0 && errno == 0) /* out of protocol EOF found */ 622 break; 623 err = "syscall error"; 624 /* 625 get_last_socket_error()); 626 */ 627 break; 628 case SSL_ERROR_SSL: 629 err = "generic SSL error"; 630 /* 631 ERR_GET_REASON(ERR_peek_error())); 632 */ 633 if (LogLevel > 9) 634 tlslogerr("write"); 635 break; 636 } 637 if (err != NULL) 638 { 639 again = MAX_TLS_IOS; 640 if (errno == 0) 641 errno = EIO; 642 if (LogLevel > 7) 643 sm_syslog(LOG_WARNING, NOQID, 644 "STARTTLS: write error=%s (%d)", err, r); 645 } 646 return r; 647 } 648 649 /* 650 ** SFDCTLS -- create tls file type and open in and out file pointers 651 ** for sendmail to read from and write to. 652 ** 653 ** Parameters: 654 ** fin -- data input source being replaced 655 ** fout -- data output source being replaced 656 ** conn -- the tls connection pointer 657 ** 658 ** Returns: 659 ** -1 on error 660 ** 0 on success 661 ** 662 ** Side effects: 663 ** The arguments "fin" and "fout" are replaced with the new 664 ** SM_FILE_T pointers. 665 ** The original "fin" and "fout" are preserved in the tls file 666 ** type but are not actually used because of the design of TLS. 667 */ 668 669 int 670 sfdctls(fin, fout, con) 671 SM_FILE_T **fin; 672 SM_FILE_T **fout; 673 SSL *con; 674 { 675 SM_FILE_T *tlsin, *tlsout; 676 SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close, 677 tls_read, tls_write, NULL, tls_getinfo, NULL, 678 SM_TIME_FOREVER); 679 struct tls_info info; 680 681 SM_ASSERT(con != NULL); 682 683 SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close, 684 tls_read, tls_write, NULL, tls_getinfo, NULL, 685 SM_TIME_FOREVER); 686 info.fp = *fin; 687 info.con = con; 688 tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY, 689 NULL); 690 if (tlsin == NULL) 691 return -1; 692 693 info.fp = *fout; 694 tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY, 695 NULL); 696 if (tlsout == NULL) 697 { 698 (void) sm_io_close(tlsin, SM_TIME_DEFAULT); 699 return -1; 700 } 701 sm_io_automode(tlsin, tlsout); 702 703 *fin = tlsin; 704 *fout = tlsout; 705 return 0; 706 } 707 #endif /* STARTTLS */ 708