Import sendmail 8.13.4 into a new contrib directory as the first step
[dragonfly.git] / contrib / sendmail-8.13.4 / sendmail / sfsasl.c
1 /*
2  * Copyright (c) 1999-2004 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.101 2004/12/15 22:45:55 ca Exp $")
13 #include <stdlib.h>
14 #include <sendmail.h>
15 #include <errno.h>
16
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 */
21
22 #if SASL
23 # include "sfsasl.h"
24
25 /* Structure used by the "sasl" file type */
26 struct sasl_obj
27 {
28         SM_FILE_T *fp;
29         sasl_conn_t *conn;
30 };
31
32 struct sasl_info
33 {
34         SM_FILE_T *fp;
35         sasl_conn_t *conn;
36 };
37
38 /*
39 **  SASL_GETINFO - returns requested information about a "sasl" file
40 **                descriptor.
41 **
42 **      Parameters:
43 **              fp -- the file descriptor
44 **              what -- the type of information requested
45 **              valp -- the thang to return the information in
46 **
47 **      Returns:
48 **              -1 for unknown requests
49 **              >=0 on success with valp filled in (if possible).
50 */
51
52 static int sasl_getinfo __P((SM_FILE_T *, int, void *));
53
54 static int
55 sasl_getinfo(fp, what, valp)
56         SM_FILE_T *fp;
57         int what;
58         void *valp;
59 {
60         struct sasl_obj *so = (struct sasl_obj *) fp->f_cookie;
61
62         switch (what)
63         {
64           case SM_IO_WHAT_FD:
65                 if (so->fp == NULL)
66                         return -1;
67                 return so->fp->f_file; /* for stdio fileno() compatability */
68
69           case SM_IO_IS_READABLE:
70                 if (so->fp == NULL)
71                         return 0;
72
73                 /* get info from underlying file */
74                 return sm_io_getinfo(so->fp, what, valp);
75
76           default:
77                 return -1;
78         }
79 }
80
81 /*
82 **  SASL_OPEN -- creates the sasl specific information for opening a
83 **              file of the sasl type.
84 **
85 **      Parameters:
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
89 **              flags -- ignored
90 **              rpool -- ignored
91 **
92 **      Returns:
93 **              0 on success
94 */
95
96 static int sasl_open __P((SM_FILE_T *, const void *, int, const void *));
97
98 /* ARGSUSED2 */
99 static int
100 sasl_open(fp, info, flags, rpool)
101         SM_FILE_T *fp;
102         const void *info;
103         int flags;
104         const void *rpool;
105 {
106         struct sasl_obj *so;
107         struct sasl_info *si = (struct sasl_info *) info;
108
109         so = (struct sasl_obj *) sm_malloc(sizeof(struct sasl_obj));
110         if (so == NULL)
111         {
112                 errno = ENOMEM;
113                 return -1;
114         }
115         so->fp = si->fp;
116         so->conn = si->conn;
117
118         /*
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.
127         */
128
129         (void) sm_io_setvbuf(so->fp, SM_TIME_DEFAULT, NULL, SM_IO_NOW, 0);
130         fp->f_cookie = so;
131         return 0;
132 }
133
134 /*
135 **  SASL_CLOSE -- close the sasl specific parts of the sasl file pointer
136 **
137 **      Parameters:
138 **              fp -- the file pointer to close
139 **
140 **      Returns:
141 **              0 on success
142 */
143
144 static int sasl_close __P((SM_FILE_T *));
145
146 static int
147 sasl_close(fp)
148         SM_FILE_T *fp;
149 {
150         struct sasl_obj *so;
151
152         so = (struct sasl_obj *) fp->f_cookie;
153         if (so == NULL)
154                 return 0;
155         if (so->fp != NULL)
156         {
157                 sm_io_close(so->fp, SM_TIME_DEFAULT);
158                 so->fp = NULL;
159         }
160         sm_free(so);
161         so = NULL;
162         return 0;
163 }
164
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)
168
169 /*
170 **  SASL_READ -- read encrypted information and decrypt it for the caller
171 **
172 **      Parameters:
173 **              fp -- the file pointer
174 **              buf -- the location to place the decrypted information
175 **              size -- the number of bytes to read after decryption
176 **
177 **      Results:
178 **              -1 on error
179 **              otherwise the number of bytes read
180 */
181
182 static ssize_t sasl_read __P((SM_FILE_T *, char *, size_t));
183
184 static ssize_t
185 sasl_read(fp, buf, size)
186         SM_FILE_T *fp;
187         char *buf;
188         size_t size;
189 {
190         int result;
191         ssize_t len;
192 # if SASL >= 20000
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;
200
201         /*
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
207         **  if necessary.
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.
211         */
212
213 # if SASL >= 20000
214         while (outlen == 0)
215 # else /* SASL >= 20000 */
216         while (outbuf == NULL && outlen == 0)
217 # endif /* SASL >= 20000 */
218         {
219                 len = sm_io_read(so->fp, SM_TIME_DEFAULT, buf, size);
220                 if (len <= 0)
221                         return len;
222                 result = sasl_decode(so->conn, buf,
223                                      (unsigned int) len, &outbuf, &outlen);
224                 if (result != SASL_OK)
225                 {
226                         outbuf = NULL;
227                         offset = 0;
228                         outlen = 0;
229                         return -1;
230                 }
231         }
232
233         if (outbuf == NULL)
234         {
235                 /* be paranoid: outbuf == NULL but outlen != 0 */
236                 syserr("@sasl_read failure: outbuf == NULL but outlen != 0");
237                 /* NOTREACHED */
238         }
239         if (outlen - offset > size)
240         {
241                 /* return another part of the buffer */
242                 (void) memcpy(buf, outbuf + offset, size);
243                 offset += size;
244                 len = size;
245         }
246         else
247         {
248                 /* return the rest of the buffer */
249                 len = outlen - offset;
250                 (void) memcpy(buf, outbuf + offset, (size_t) len);
251 # if SASL < 20000
252                 SASL_DEALLOC(outbuf);
253 # endif /* SASL < 20000 */
254                 outbuf = NULL;
255                 offset = 0;
256                 outlen = 0;
257         }
258         return len;
259 }
260
261 /*
262 **  SASL_WRITE -- write information out after encrypting it
263 **
264 **      Parameters:
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
268 **
269 **      Returns:
270 **              -1 on error
271 **              otherwise number of bytes written
272 */
273
274 static ssize_t sasl_write __P((SM_FILE_T *, const char *, size_t));
275
276 static ssize_t
277 sasl_write(fp, buf, size)
278         SM_FILE_T *fp;
279         const char *buf;
280         size_t size;
281 {
282         int result;
283 # if SASL >= 20000
284         const char *outbuf;
285 # else /* SASL >= 20000 */
286         char *outbuf;
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;
291
292         /*
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.
304         */
305
306         result = sasl_getprop(so->conn, SASL_MAXOUTBUF,
307                              (const void **) &maxencode);
308         if (result == SASL_OK && size > *maxencode && *maxencode > 0)
309                 size = *maxencode;
310
311         result = sasl_encode(so->conn, buf,
312                              (unsigned int) size, &outbuf, &outlen);
313
314         if (result != SASL_OK)
315                 return -1;
316
317         if (outbuf != NULL)
318         {
319                 while (outlen > 0)
320                 {
321                         /* XXX result == 0? */
322                         ret = sm_io_write(so->fp, SM_TIME_DEFAULT,
323                                           &outbuf[total], outlen);
324                         if (ret <= 0)
325                                 return ret;
326                         outlen -= ret;
327                         total += ret;
328                 }
329 # if SASL < 20000
330                 SASL_DEALLOC(outbuf);
331 # endif /* SASL < 20000 */
332         }
333         return size;
334 }
335
336 /*
337 **  SFDCSASL -- create sasl file type and open in and out file pointers
338 **             for sendmail to read from and write to.
339 **
340 **      Parameters:
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
344 **
345 **      Returns:
346 **              -1 on error
347 **              0 on success
348 **
349 **      Side effects:
350 **              The arguments "fin" and "fout" are replaced with the new
351 **              SM_FILE_T pointers.
352 */
353
354 int
355 sfdcsasl(fin, fout, conn)
356         SM_FILE_T **fin;
357         SM_FILE_T **fout;
358         sasl_conn_t *conn;
359 {
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,
363                 SM_TIME_FOREVER);
364         struct sasl_info info;
365
366         if (conn == NULL)
367         {
368                 /* no need to do anything */
369                 return 0;
370         }
371
372         SM_IO_INIT_TYPE(sasl_vector, "sasl", sasl_open, sasl_close,
373                 sasl_read, sasl_write, NULL, sasl_getinfo, NULL,
374                 SM_TIME_FOREVER);
375         info.fp = *fin;
376         info.conn = conn;
377         newin = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
378                         SM_IO_RDONLY_B, NULL);
379
380         if (newin == NULL)
381                 return -1;
382
383         info.fp = *fout;
384         info.conn = conn;
385         newout = sm_io_open(&sasl_vector, SM_TIME_DEFAULT, &info,
386                         SM_IO_WRONLY_B, NULL);
387
388         if (newout == NULL)
389         {
390                 (void) sm_io_close(newin, SM_TIME_DEFAULT);
391                 return -1;
392         }
393         sm_io_automode(newin, newout);
394
395         *fin = newin;
396         *fout = newout;
397         return 0;
398 }
399 #endif /* SASL */
400
401 #if STARTTLS
402 # include "sfsasl.h"
403 #  include <openssl/err.h>
404
405 /* Structure used by the "tls" file type */
406 struct tls_obj
407 {
408         SM_FILE_T *fp;
409         SSL *con;
410 };
411
412 struct tls_info
413 {
414         SM_FILE_T *fp;
415         SSL *con;
416 };
417
418 /*
419 **  TLS_GETINFO - returns requested information about a "tls" file
420 **               descriptor.
421 **
422 **      Parameters:
423 **              fp -- the file descriptor
424 **              what -- the type of information requested
425 **              valp -- the thang to return the information in (unused)
426 **
427 **      Returns:
428 **              -1 for unknown requests
429 **              >=0 on success with valp filled in (if possible).
430 */
431
432 static int tls_getinfo __P((SM_FILE_T *, int, void *));
433
434 /* ARGSUSED2 */
435 static int
436 tls_getinfo(fp, what, valp)
437         SM_FILE_T *fp;
438         int what;
439         void *valp;
440 {
441         struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
442
443         switch (what)
444         {
445           case SM_IO_WHAT_FD:
446                 if (so->fp == NULL)
447                         return -1;
448                 return so->fp->f_file; /* for stdio fileno() compatability */
449
450           case SM_IO_IS_READABLE:
451                 return SSL_pending(so->con) > 0;
452
453           default:
454                 return -1;
455         }
456 }
457
458 /*
459 **  TLS_OPEN -- creates the tls specific information for opening a
460 **             file of the tls type.
461 **
462 **      Parameters:
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
466 **              flags -- ignored
467 **              rpool -- ignored
468 **
469 **      Returns:
470 **              0 on success
471 */
472
473 static int tls_open __P((SM_FILE_T *, const void *, int, const void *));
474
475 /* ARGSUSED2 */
476 static int
477 tls_open(fp, info, flags, rpool)
478         SM_FILE_T *fp;
479         const void *info;
480         int flags;
481         const void *rpool;
482 {
483         struct tls_obj *so;
484         struct tls_info *ti = (struct tls_info *) info;
485
486         so = (struct tls_obj *) sm_malloc(sizeof(struct tls_obj));
487         if (so == NULL)
488         {
489                 errno = ENOMEM;
490                 return -1;
491         }
492         so->fp = ti->fp;
493         so->con = ti->con;
494
495         /*
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.
501         */
502
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);
505         fp->f_cookie = so;
506         return 0;
507 }
508
509 /*
510 **  TLS_CLOSE -- close the tls specific parts of the tls file pointer
511 **
512 **      Parameters:
513 **              fp -- the file pointer to close
514 **
515 **      Returns:
516 **              0 on success
517 */
518
519 static int tls_close __P((SM_FILE_T *));
520
521 static int
522 tls_close(fp)
523         SM_FILE_T *fp;
524 {
525         struct tls_obj *so;
526
527         so = (struct tls_obj *) fp->f_cookie;
528         if (so == NULL)
529                 return 0;
530         if (so->fp != NULL)
531         {
532                 sm_io_close(so->fp, SM_TIME_DEFAULT);
533                 so->fp = NULL;
534         }
535         sm_free(so);
536         so = NULL;
537         return 0;
538 }
539
540 /* maximum number of retries for TLS related I/O due to handshakes */
541 # define MAX_TLS_IOS    4
542
543 /*
544 **  TLS_READ -- read secured information for the caller
545 **
546 **      Parameters:
547 **              fp -- the file pointer
548 **              buf -- the location to place the data
549 **              size -- the number of bytes to read from connection
550 **
551 **      Results:
552 **              -1 on error
553 **              otherwise the number of bytes read
554 */
555
556 static ssize_t tls_read __P((SM_FILE_T *, char *, size_t));
557
558 static ssize_t
559 tls_read(fp, buf, size)
560         SM_FILE_T *fp;
561         char *buf;
562         size_t size;
563 {
564         int r;
565         static int again = MAX_TLS_IOS;
566         struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
567         char *err;
568
569         r = SSL_read(so->con, (char *) buf, size);
570
571         if (r > 0)
572         {
573                 again = MAX_TLS_IOS;
574                 return r;
575         }
576
577         err = NULL;
578         switch (SSL_get_error(so->con, r))
579         {
580           case SSL_ERROR_NONE:
581           case SSL_ERROR_ZERO_RETURN:
582                 again = MAX_TLS_IOS;
583                 break;
584           case SSL_ERROR_WANT_WRITE:
585                 if (--again <= 0)
586                         err = "read W BLOCK";
587                 else
588                         errno = EAGAIN;
589                 break;
590           case SSL_ERROR_WANT_READ:
591                 if (--again <= 0)
592                         err = "read R BLOCK";
593                 else
594                         errno = EAGAIN;
595                 break;
596           case SSL_ERROR_WANT_X509_LOOKUP:
597                 err = "write X BLOCK";
598                 break;
599           case SSL_ERROR_SYSCALL:
600                 if (r == 0 && errno == 0) /* out of protocol EOF found */
601                         break;
602                 err = "syscall error";
603 /*
604                 get_last_socket_error());
605 */
606                 break;
607           case SSL_ERROR_SSL:
608 #if DEAL_WITH_ERROR_SSL
609                 if (r == 0 && errno == 0) /* out of protocol EOF found */
610                         break;
611 #endif /* DEAL_WITH_ERROR_SSL */
612                 err = "generic SSL error";
613                 if (LogLevel > 9)
614                         tlslogerr("read");
615
616 #if DEAL_WITH_ERROR_SSL
617                 /* avoid repeated calls? */
618                 if (r == 0)
619                         r = -1;
620 #endif /* DEAL_WITH_ERROR_SSL */
621                 break;
622         }
623         if (err != NULL)
624         {
625                 int save_errno;
626
627                 save_errno = (errno == 0) ? EIO : errno;
628                 again = MAX_TLS_IOS;
629                 if (LogLevel > 9)
630                         sm_syslog(LOG_WARNING, NOQID,
631                                   "STARTTLS: read error=%s (%d), errno=%d, get_error=%s",
632                                   err, r, errno,
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);
637                 errno = save_errno;
638         }
639         return r;
640 }
641
642 /*
643 **  TLS_WRITE -- write information out through secure connection
644 **
645 **      Parameters:
646 **              fp -- the file pointer
647 **              buf -- holds the data to be securely written
648 **              size -- the number of bytes to write
649 **
650 **      Returns:
651 **              -1 on error
652 **              otherwise number of bytes written
653 */
654
655 static ssize_t tls_write __P((SM_FILE_T *, const char *, size_t));
656
657 static ssize_t
658 tls_write(fp, buf, size)
659         SM_FILE_T *fp;
660         const char *buf;
661         size_t size;
662 {
663         int r;
664         static int again = MAX_TLS_IOS;
665         struct tls_obj *so = (struct tls_obj *) fp->f_cookie;
666         char *err;
667
668         r = SSL_write(so->con, (char *) buf, size);
669
670         if (r > 0)
671         {
672                 again = MAX_TLS_IOS;
673                 return r;
674         }
675         err = NULL;
676         switch (SSL_get_error(so->con, r))
677         {
678           case SSL_ERROR_NONE:
679           case SSL_ERROR_ZERO_RETURN:
680                 again = MAX_TLS_IOS;
681                 break;
682           case SSL_ERROR_WANT_WRITE:
683                 if (--again <= 0)
684                         err = "write W BLOCK";
685                 else
686                         errno = EAGAIN;
687                 break;
688           case SSL_ERROR_WANT_READ:
689                 if (--again <= 0)
690                         err = "write R BLOCK";
691                 else
692                         errno = EAGAIN;
693                 break;
694           case SSL_ERROR_WANT_X509_LOOKUP:
695                 err = "write X BLOCK";
696                 break;
697           case SSL_ERROR_SYSCALL:
698                 if (r == 0 && errno == 0) /* out of protocol EOF found */
699                         break;
700                 err = "syscall error";
701 /*
702                 get_last_socket_error());
703 */
704                 break;
705           case SSL_ERROR_SSL:
706                 err = "generic SSL error";
707 /*
708                 ERR_GET_REASON(ERR_peek_error()));
709 */
710                 if (LogLevel > 9)
711                         tlslogerr("write");
712
713 #if DEAL_WITH_ERROR_SSL
714                 /* avoid repeated calls? */
715                 if (r == 0)
716                         r = -1;
717 #endif /* DEAL_WITH_ERROR_SSL */
718                 break;
719         }
720         if (err != NULL)
721         {
722                 int save_errno;
723
724                 save_errno = (errno == 0) ? EIO : errno;
725                 again = MAX_TLS_IOS;
726                 if (LogLevel > 9)
727                         sm_syslog(LOG_WARNING, NOQID,
728                                   "STARTTLS: write error=%s (%d), errno=%d, get_error=%s",
729                                   err, r, errno,
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);
734                 errno = save_errno;
735         }
736         return r;
737 }
738
739 /*
740 **  SFDCTLS -- create tls file type and open in and out file pointers
741 **            for sendmail to read from and write to.
742 **
743 **      Parameters:
744 **              fin -- data input source being replaced
745 **              fout -- data output source being replaced
746 **              con -- the tls connection pointer
747 **
748 **      Returns:
749 **              -1 on error
750 **              0 on success
751 **
752 **      Side effects:
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.
757 */
758
759 int
760 sfdctls(fin, fout, con)
761         SM_FILE_T **fin;
762         SM_FILE_T **fout;
763         SSL *con;
764 {
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,
768                 SM_TIME_FOREVER);
769         struct tls_info info;
770
771         SM_ASSERT(con != NULL);
772
773         SM_IO_INIT_TYPE(tls_vector, "tls", tls_open, tls_close,
774                 tls_read, tls_write, NULL, tls_getinfo, NULL,
775                 SM_TIME_FOREVER);
776         info.fp = *fin;
777         info.con = con;
778         tlsin = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_RDONLY_B,
779                            NULL);
780         if (tlsin == NULL)
781                 return -1;
782
783         info.fp = *fout;
784         tlsout = sm_io_open(&tls_vector, SM_TIME_DEFAULT, &info, SM_IO_WRONLY_B,
785                             NULL);
786         if (tlsout == NULL)
787         {
788                 (void) sm_io_close(tlsin, SM_TIME_DEFAULT);
789                 return -1;
790         }
791         sm_io_automode(tlsin, tlsout);
792
793         *fin = tlsin;
794         *fout = tlsout;
795         return 0;
796 }
797 #endif /* STARTTLS */