2 * Copyright (c) 1999-2003 Sendmail, Inc. and its suppliers.
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.
12 SM_RCSID("@(#)$Id: sfsasl.c,v 8.91.2.5 2003/08/08 17:30:11 ca Exp $")
19 /* Structure used by the "sasl" file type */
33 ** SASL_GETINFO - returns requested information about a "sasl" file
37 ** fp -- the file descriptor
38 ** what -- the type of information requested
39 ** valp -- the thang to return the information in
42 ** -1 for unknown requests
43 ** >=0 on success with valp filled in (if possible).
46 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
49 sasl_getinfo(fp, what, valp)
54 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
61 return so->fp->f_file; /* for stdio fileno() compatability */
63 case SM_IO_IS_READABLE:
67 /* get info from underlying file */
68 return sm_io_getinfo(so->fp, what, valp);
76 ** SASL_OPEN -- creates the sasl specific information for opening a
77 ** file of the sasl type.
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
90 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
94 sasl_open(fp, info, flags, rpool)
101 struct sasl_info *si = (struct sasl_info *) info;
103 so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
113 ** The underlying 'fp' is set to SM_IO_NOW so that the entire
114 ** encoded string is written in one chunk. Otherwise there is
115 ** the possibility that it may appear illegal, bogus or
116 ** mangled to the other side of the connection.
117 ** We will read or write through 'fp' since it is the opaque
118 ** connection for the communications. We need to treat it this
119 ** way in case the encoded string is to be sent down a TLS
120 ** connection rather than, say, sm_io's stdio.
123 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
129 ** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
132 ** fp -- the file pointer to close
138 static int sasl_close __P((SM_FILE_T *));
146 so = (struct sasl_obj *) fp->f_cookie;
151 sm_io_close(so->fp, SM_TIME_DEFAULT);
159 /* how to deallocate a buffer allocated by SASL */
160 extern void sm_sasl_free __P((void *));
161 # define SASL_DEALLOC(b) sm_sasl_free(b)
164 ** SASL_READ -- read encrypted information and decrypt it for the caller
167 ** fp -- the file pointer
168 ** buf -- the location to place the decrypted information
169 ** size -- the number of bytes to read after decryption
173 ** otherwise the number of bytes read
176 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
179 sasl_read(fp, buf, size)
187 static const char *outbuf = NULL;
188 # else /* SASL >= 20000 */
189 static char *outbuf = NULL;
190 # endif /* SASL >= 20000 */
191 static unsigned int outlen = 0;
192 static unsigned int offset = 0;
193 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
196 ** sasl_decode() may require more data than a single read() returns.
197 ** Hence we have to put a loop around the decoding.
198 ** This also requires that we may have to split up the returned
199 ** data since it might be larger than the allowed size.
200 ** Therefore we use a static pointer and return portions of it
202 ** XXX Note: This function is not thread-safe nor can it be used
203 ** on more than one file. A correct implementation would store
204 ** this data in fp->f_cookie.
209 # else /* SASL >= 20000 */
210 while (outbuf == NULL && outlen == 0)
211 # endif /* SASL >= 20000 */
213 len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
216 result = sasl_decode(so->conn, buf,
217 (unsigned int) len, &outbuf, &outlen);
218 if (result != SASL_OK)
229 /* be paranoid: outbuf == NULL but outlen != 0 */
230 syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
233 if (outlen - offset > size)
235 /* return another part of the buffer */
236 (void) memcpy(buf, outbuf + offset, size);
242 /* return the rest of the buffer */
243 len = outlen - offset;
244 (void) memcpy(buf, outbuf + offset, (size_t) len);
246 SASL_DEALLOC(outbuf);
247 # endif /* SASL < 20000 */
256 ** SASL_WRITE -- write information out after encrypting it
259 ** fp -- the file pointer
260 ** buf -- holds the data to be encrypted and written
261 ** size -- the number of bytes to have encrypted and written
265 ** otherwise number of bytes written
268 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
271 sasl_write(fp, buf, size)
279 # else /* SASL >= 20000 */
281 # endif /* SASL >= 20000 */
283 size_t ret = 0, total = 0;
284 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
286 result = sasl_encode(so->conn, buf,
287 (unsigned int) size, &outbuf, &outlen);
289 if (result != SASL_OK)
296 /* XXX result == 0? */
297 ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
298 &outbuf[total], outlen);
305 SASL_DEALLOC(outbuf);
306 # endif /* SASL < 20000 */
312 ** SFDCSASL -- create sasl file type and open in and out file pointers
313 ** for sendmail to read from and write to.
316 ** fin -- the sm_io file encrypted data to be read from
317 ** fout -- the sm_io file encrypted data to be writen to
318 ** conn -- the sasl connection pointer
325 ** The arguments "fin" and "fout" are replaced with the new
326 ** SM_FILE_T pointers.
330 sfdcsasl(fin, fout, conn)
335 SM_FILE_T *newin, *newout;
336 SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
337 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
339 struct sasl_info info;
343 /* no need to do anything */
347 SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
348 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
352 newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY,
360 newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY,
365 (void) sm_io_close(newin, SM_TIME_DEFAULT);
368 sm_io_automode(newin, newout);
378 # include <openssl/err.h>
380 /* Structure used by the "tls" file type */
394 ** TLS_GETINFO - returns requested information about a "tls" file
398 ** fp -- the file descriptor
399 ** what -- the type of information requested
400 ** valp -- the thang to return the information in (unused)
403 ** -1 for unknown requests
404 ** >=0 on success with valp filled in (if possible).
407 static int tls_getinfo __P((SM_FILE_T *, int, void *));
411 tls_getinfo(fp, what, valp)
416 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
423 return so->fp->f_file; /* for stdio fileno() compatability */
425 case SM_IO_IS_READABLE:
426 return SSL_pending(so->con) > 0;
434 ** TLS_OPEN -- creates the tls specific information for opening a
435 ** file of the tls type.
438 ** fp -- the file pointer associated with the new open
439 ** info -- the sm_io file pointer holding the open and the
440 ** TLS encryption connection to be read from or written to
448 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
452 tls_open(fp, info, flags, rpool)
459 struct tls_info *ti = (struct tls_info *) info;
461 so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
471 ** We try to get the "raw" file descriptor that TLS uses to
472 ** do the actual read/write with. This is to allow us control
473 ** over the file descriptor being a blocking or non-blocking type.
474 ** Under the covers TLS handles the change and this allows us
475 ** to do timeouts with sm_io.
478 fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL);
479 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
485 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer
488 ** fp -- the file pointer to close
494 static int tls_close __P((SM_FILE_T *));
502 so = (struct tls_obj *) fp->f_cookie;
507 sm_io_close(so->fp, SM_TIME_DEFAULT);
515 /* maximum number of retries for TLS related I/O due to handshakes */
516 # define MAX_TLS_IOS 4
519 ** TLS_READ -- read secured information for the caller
522 ** fp -- the file pointer
523 ** buf -- the location to place the data
524 ** size -- the number of bytes to read from connection
528 ** otherwise the number of bytes read
531 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
534 tls_read(fp, buf, size)
540 static int again = MAX_TLS_IOS;
541 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
544 r = SSL_read(so->con, (char *) buf, size);
553 switch (SSL_get_error(so->con, r))
556 case SSL_ERROR_ZERO_RETURN:
559 case SSL_ERROR_WANT_WRITE:
561 err = "read W BLOCK";
565 case SSL_ERROR_WANT_READ:
567 err = "read R BLOCK";
571 case SSL_ERROR_WANT_X509_LOOKUP:
572 err = "write X BLOCK";
574 case SSL_ERROR_SYSCALL:
575 if (r == 0 && errno == 0) /* out of protocol EOF found */
577 err = "syscall error";
579 get_last_socket_error());
583 #if _FFR_DEAL_WITH_ERROR_SSL
584 if (r == 0 && errno == 0) /* out of protocol EOF found */
586 #endif /* _FFR_DEAL_WITH_ERROR_SSL */
587 err = "generic SSL error";
591 #if _FFR_DEAL_WITH_ERROR_SSL
592 /* avoid repeated calls? */
595 #endif /* _FFR_DEAL_WITH_ERROR_SSL */
602 save_errno = (errno == 0) ? EIO : errno;
605 sm_syslog(LOG_WARNING, NOQID,
606 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
608 ERR_error_string(ERR_get_error(), NULL));
609 else if (LogLevel > 7)
610 sm_syslog(LOG_WARNING, NOQID,
611 "STARTTLS: read error=%s (%d)", err, r);
618 ** TLS_WRITE -- write information out through secure connection
621 ** fp -- the file pointer
622 ** buf -- holds the data to be securely written
623 ** size -- the number of bytes to write
627 ** otherwise number of bytes written
630 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
633 tls_write(fp, buf, size)
639 static int again = MAX_TLS_IOS;
640 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
643 r = SSL_write(so->con, (char *) buf, size);
651 switch (SSL_get_error(so->con, r))
654 case SSL_ERROR_ZERO_RETURN:
657 case SSL_ERROR_WANT_WRITE:
659 err = "write W BLOCK";
663 case SSL_ERROR_WANT_READ:
665 err = "write R BLOCK";
669 case SSL_ERROR_WANT_X509_LOOKUP:
670 err = "write X BLOCK";
672 case SSL_ERROR_SYSCALL:
673 if (r == 0 && errno == 0) /* out of protocol EOF found */
675 err = "syscall error";
677 get_last_socket_error());
681 err = "generic SSL error";
683 ERR_GET_REASON(ERR_peek_error()));
688 #if _FFR_DEAL_WITH_ERROR_SSL
689 /* avoid repeated calls? */
692 #endif /* _FFR_DEAL_WITH_ERROR_SSL */
699 save_errno = (errno == 0) ? EIO : errno;
702 sm_syslog(LOG_WARNING, NOQID,
703 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
705 ERR_error_string(ERR_get_error(), NULL));
706 else if (LogLevel > 7)
707 sm_syslog(LOG_WARNING, NOQID,
708 "STARTTLS: write error=%s (%d)", err, r);
715 ** SFDCTLS -- create tls file type and open in and out file pointers
716 ** for sendmail to read from and write to.
719 ** fin -- data input source being replaced
720 ** fout -- data output source being replaced
721 ** con -- the tls connection pointer
728 ** The arguments "fin" and "fout" are replaced with the new
729 ** SM_FILE_T pointers.
730 ** The original "fin" and "fout" are preserved in the tls file
731 ** type but are not actually used because of the design of TLS.
735 sfdctls(fin, fout, con)
740 SM_FILE_T *tlsin, *tlsout;
741 SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
742 tls_read, tls_write, NULL, tls_getinfo, NULL,
744 struct tls_info info;
746 SM_ASSERT(con != NULL);
748 SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
749 tls_read, tls_write, NULL, tls_getinfo, NULL,
753 tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY,
759 tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY,
763 (void) sm_io_close(tlsin, SM_TIME_DEFAULT);
766 sm_io_automode(tlsin, tlsout);
772 #endif /* STARTTLS */