2 * Copyright (c) 1999-2004 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.101 2004/12/15 22:45:55 ca Exp $")
17 /* allow to disable error handling code just in case... */
18 #ifndef DEAL_WITH_ERROR_SSL
19 # define DEAL_WITH_ERROR_SSL 1
20 #endif /* ! DEAL_WITH_ERROR_SSL */
25 /* Structure used by the "sasl" file type */
39 ** SASL_GETINFO - returns requested information about a "sasl" file
43 ** fp -- the file descriptor
44 ** what -- the type of information requested
45 ** valp -- the thang to return the information in
48 ** -1 for unknown requests
49 ** >=0 on success with valp filled in (if possible).
52 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
55 sasl_getinfo(fp, what, valp)
60 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
67 return so->fp->f_file; /* for stdio fileno() compatability */
69 case SM_IO_IS_READABLE:
73 /* get info from underlying file */
74 return sm_io_getinfo(so->fp, what, valp);
82 ** SASL_OPEN -- creates the sasl specific information for opening a
83 ** file of the sasl type.
86 ** fp -- the file pointer associated with the new open
87 ** info -- contains the sasl connection information pointer and
88 ** the original SM_FILE_T that holds the open
96 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
100 sasl_open(fp, info, flags, rpool)
107 struct sasl_info *si = (struct sasl_info *) info;
109 so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
119 ** The underlying 'fp' is set to SM_IO_NOW so that the entire
120 ** encoded string is written in one chunk. Otherwise there is
121 ** the possibility that it may appear illegal, bogus or
122 ** mangled to the other side of the connection.
123 ** We will read or write through 'fp' since it is the opaque
124 ** connection for the communications. We need to treat it this
125 ** way in case the encoded string is to be sent down a TLS
126 ** connection rather than, say, sm_io's stdio.
129 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
135 ** SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
138 ** fp -- the file pointer to close
144 static int sasl_close __P((SM_FILE_T *));
152 so = (struct sasl_obj *) fp->f_cookie;
157 sm_io_close(so->fp, SM_TIME_DEFAULT);
165 /* how to deallocate a buffer allocated by SASL */
166 extern void sm_sasl_free __P((void *));
167 # define SASL_DEALLOC(b) sm_sasl_free(b)
170 ** SASL_READ -- read encrypted information and decrypt it for the caller
173 ** fp -- the file pointer
174 ** buf -- the location to place the decrypted information
175 ** size -- the number of bytes to read after decryption
179 ** otherwise the number of bytes read
182 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
185 sasl_read(fp, buf, size)
193 static const char *outbuf = NULL;
194 # else /* SASL >= 20000 */
195 static char *outbuf = NULL;
196 # endif /* SASL >= 20000 */
197 static unsigned int outlen = 0;
198 static unsigned int offset = 0;
199 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
202 ** sasl_decode() may require more data than a single read() returns.
203 ** Hence we have to put a loop around the decoding.
204 ** This also requires that we may have to split up the returned
205 ** data since it might be larger than the allowed size.
206 ** Therefore we use a static pointer and return portions of it
208 ** XXX Note: This function is not thread-safe nor can it be used
209 ** on more than one file. A correct implementation would store
210 ** this data in fp->f_cookie.
215 # else /* SASL >= 20000 */
216 while (outbuf == NULL && outlen == 0)
217 # endif /* SASL >= 20000 */
219 len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
222 result = sasl_decode(so->conn, buf,
223 (unsigned int) len, &outbuf, &outlen);
224 if (result != SASL_OK)
235 /* be paranoid: outbuf == NULL but outlen != 0 */
236 syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
239 if (outlen - offset > size)
241 /* return another part of the buffer */
242 (void) memcpy(buf, outbuf + offset, size);
248 /* return the rest of the buffer */
249 len = outlen - offset;
250 (void) memcpy(buf, outbuf + offset, (size_t) len);
252 SASL_DEALLOC(outbuf);
253 # endif /* SASL < 20000 */
262 ** SASL_WRITE -- write information out after encrypting it
265 ** fp -- the file pointer
266 ** buf -- holds the data to be encrypted and written
267 ** size -- the number of bytes to have encrypted and written
271 ** otherwise number of bytes written
274 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
277 sasl_write(fp, buf, size)
285 # else /* SASL >= 20000 */
287 # endif /* SASL >= 20000 */
288 unsigned int outlen, *maxencode;
289 size_t ret = 0, total = 0;
290 struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
293 ** Fetch the maximum input buffer size for sasl_encode().
294 ** This can be less than the size set in attemptauth()
295 ** due to a negotation with the other side, e.g.,
296 ** Cyrus IMAP lmtp program sets maxbuf=4096,
297 ** digestmd5 substracts 25 and hence we'll get 4071
298 ** instead of 8192 (MAXOUTLEN).
299 ** Hack (for now): simply reduce the size, callers are (must be)
300 ** able to deal with that and invoke sasl_write() again with
301 ** the rest of the data.
302 ** Note: it would be better to store this value in the context
303 ** after the negotiation.
306 result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
307 (const void **) &maxencode);
308 if (result == SASL_OK && size > *maxencode && *maxencode > 0)
311 result = sasl_encode(so->conn, buf,
312 (unsigned int) size, &outbuf, &outlen);
314 if (result != SASL_OK)
321 /* XXX result == 0? */
322 ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
323 &outbuf[total], outlen);
330 SASL_DEALLOC(outbuf);
331 # endif /* SASL < 20000 */
337 ** SFDCSASL -- create sasl file type and open in and out file pointers
338 ** for sendmail to read from and write to.
341 ** fin -- the sm_io file encrypted data to be read from
342 ** fout -- the sm_io file encrypted data to be writen to
343 ** conn -- the sasl connection pointer
350 ** The arguments "fin" and "fout" are replaced with the new
351 ** SM_FILE_T pointers.
355 sfdcsasl(fin, fout, conn)
360 SM_FILE_T *newin, *newout;
361 SM_FILE_T SM_IO_SET_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
362 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
364 struct sasl_info info;
368 /* no need to do anything */
372 SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
373 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
377 newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
378 SM_IO_RDONLY_B, NULL);
385 newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
386 SM_IO_WRONLY_B, NULL);
390 (void) sm_io_close(newin, SM_TIME_DEFAULT);
393 sm_io_automode(newin, newout);
403 # include <openssl/err.h>
405 /* Structure used by the "tls" file type */
419 ** TLS_GETINFO - returns requested information about a "tls" file
423 ** fp -- the file descriptor
424 ** what -- the type of information requested
425 ** valp -- the thang to return the information in (unused)
428 ** -1 for unknown requests
429 ** >=0 on success with valp filled in (if possible).
432 static int tls_getinfo __P((SM_FILE_T *, int, void *));
436 tls_getinfo(fp, what, valp)
441 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
448 return so->fp->f_file; /* for stdio fileno() compatability */
450 case SM_IO_IS_READABLE:
451 return SSL_pending(so->con) > 0;
459 ** TLS_OPEN -- creates the tls specific information for opening a
460 ** file of the tls type.
463 ** fp -- the file pointer associated with the new open
464 ** info -- the sm_io file pointer holding the open and the
465 ** TLS encryption connection to be read from or written to
473 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
477 tls_open(fp, info, flags, rpool)
484 struct tls_info *ti = (struct tls_info *) info;
486 so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
496 ** We try to get the "raw" file descriptor that TLS uses to
497 ** do the actual read/write with. This is to allow us control
498 ** over the file descriptor being a blocking or non-blocking type.
499 ** Under the covers TLS handles the change and this allows us
500 ** to do timeouts with sm_io.
503 fp->f_file = sm_io_getinfo(so->fp, SM_IO_WHAT_FD, NULL);
504 (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
510 ** TLS_CLOSE -- close the tls specific parts of the tls file pointer
513 ** fp -- the file pointer to close
519 static int tls_close __P((SM_FILE_T *));
527 so = (struct tls_obj *) fp->f_cookie;
532 sm_io_close(so->fp, SM_TIME_DEFAULT);
540 /* maximum number of retries for TLS related I/O due to handshakes */
541 # define MAX_TLS_IOS 4
544 ** TLS_READ -- read secured information for the caller
547 ** fp -- the file pointer
548 ** buf -- the location to place the data
549 ** size -- the number of bytes to read from connection
553 ** otherwise the number of bytes read
556 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
559 tls_read(fp, buf, size)
565 static int again = MAX_TLS_IOS;
566 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
569 r = SSL_read(so->con, (char *) buf, size);
578 switch (SSL_get_error(so->con, r))
581 case SSL_ERROR_ZERO_RETURN:
584 case SSL_ERROR_WANT_WRITE:
586 err = "read W BLOCK";
590 case SSL_ERROR_WANT_READ:
592 err = "read R BLOCK";
596 case SSL_ERROR_WANT_X509_LOOKUP:
597 err = "write X BLOCK";
599 case SSL_ERROR_SYSCALL:
600 if (r == 0 && errno == 0) /* out of protocol EOF found */
602 err = "syscall error";
604 get_last_socket_error());
608 #if DEAL_WITH_ERROR_SSL
609 if (r == 0 && errno == 0) /* out of protocol EOF found */
611 #endif /* DEAL_WITH_ERROR_SSL */
612 err = "generic SSL error";
616 #if DEAL_WITH_ERROR_SSL
617 /* avoid repeated calls? */
620 #endif /* DEAL_WITH_ERROR_SSL */
627 save_errno = (errno == 0) ? EIO : errno;
630 sm_syslog(LOG_WARNING, NOQID,
631 "STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
633 ERR_error_string(ERR_get_error(), NULL));
634 else if (LogLevel > 7)
635 sm_syslog(LOG_WARNING, NOQID,
636 "STARTTLS: read error=%s (%d)", err, r);
643 ** TLS_WRITE -- write information out through secure connection
646 ** fp -- the file pointer
647 ** buf -- holds the data to be securely written
648 ** size -- the number of bytes to write
652 ** otherwise number of bytes written
655 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
658 tls_write(fp, buf, size)
664 static int again = MAX_TLS_IOS;
665 struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
668 r = SSL_write(so->con, (char *) buf, size);
676 switch (SSL_get_error(so->con, r))
679 case SSL_ERROR_ZERO_RETURN:
682 case SSL_ERROR_WANT_WRITE:
684 err = "write W BLOCK";
688 case SSL_ERROR_WANT_READ:
690 err = "write R BLOCK";
694 case SSL_ERROR_WANT_X509_LOOKUP:
695 err = "write X BLOCK";
697 case SSL_ERROR_SYSCALL:
698 if (r == 0 && errno == 0) /* out of protocol EOF found */
700 err = "syscall error";
702 get_last_socket_error());
706 err = "generic SSL error";
708 ERR_GET_REASON(ERR_peek_error()));
713 #if DEAL_WITH_ERROR_SSL
714 /* avoid repeated calls? */
717 #endif /* DEAL_WITH_ERROR_SSL */
724 save_errno = (errno == 0) ? EIO : errno;
727 sm_syslog(LOG_WARNING, NOQID,
728 "STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
730 ERR_error_string(ERR_get_error(), NULL));
731 else if (LogLevel > 7)
732 sm_syslog(LOG_WARNING, NOQID,
733 "STARTTLS: write error=%s (%d)", err, r);
740 ** SFDCTLS -- create tls file type and open in and out file pointers
741 ** for sendmail to read from and write to.
744 ** fin -- data input source being replaced
745 ** fout -- data output source being replaced
746 ** con -- the tls connection pointer
753 ** The arguments "fin" and "fout" are replaced with the new
754 ** SM_FILE_T pointers.
755 ** The original "fin" and "fout" are preserved in the tls file
756 ** type but are not actually used because of the design of TLS.
760 sfdctls(fin, fout, con)
765 SM_FILE_T *tlsin, *tlsout;
766 SM_FILE_T SM_IO_SET_TYPE(tls_vector, "tls", tls_open, tls_close,
767 tls_read, tls_write, NULL, tls_getinfo, NULL,
769 struct tls_info info;
771 SM_ASSERT(con != NULL);
773 SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
774 tls_read, tls_write, NULL, tls_getinfo, NULL,
778 tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
784 tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
788 (void) sm_io_close(tlsin, SM_TIME_DEFAULT);
791 sm_io_automode(tlsin, tlsout);
797 #endif /* STARTTLS */