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