[SVN] r713 - in /branches/sarge-2.2.13-cyradm-tls: ./
debian/patches/00list debian/patches/66-cyradm-tls-enabled.dpatch
debian at incase.de
debian at incase.de
Thu Mar 8 16:55:37 CET 2007
Author: sven
Date: Thu Mar 8 16:55:34 2007
New Revision: 713
URL: https://mail.incase.de/viewcvs?rev=713&root=cyrus22&view=rev
Log:
Add experimental branch of 2.2.13 with TLS support in cyradm and managesieve
Added:
branches/sarge-2.2.13-cyradm-tls/
- copied from r712, branches/sarge-2.2.13/
branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch (with props)
Modified:
branches/sarge-2.2.13-cyradm-tls/debian/patches/00list
Modified: branches/sarge-2.2.13-cyradm-tls/debian/patches/00list
URL: https://mail.incase.de/viewcvs/branches/sarge-2.2.13-cyradm-tls/debian/patches/00list?rev=713&root=cyrus22&r1=712&r2=713&view=diff
==============================================================================
--- branches/sarge-2.2.13-cyradm-tls/debian/patches/00list (original)
+++ branches/sarge-2.2.13-cyradm-tls/debian/patches/00list Thu Mar 8 16:55:34 2007
@@ -50,6 +50,7 @@
45-kolab2-annotations.dpatch
61-64bit-quota.dpatch
65-sieveshell-enhancements.dpatch
+66-cyradm-tls-enabled.dpatch
70-allow-larger-buffers.dpatch
72-faster-isdigit.dpatch
75-update-imapd.conf-documentation.dpatch
Added: branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch
URL: https://mail.incase.de/viewcvs/branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch?rev=713&root=cyrus22&view=auto
==============================================================================
--- branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch (added)
+++ branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch Thu Mar 8 16:55:34 2007
@@ -1,0 +1,2394 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## fileUtqrG1.dpatch by Sven Mueller <sven at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed /tmp/dpep.9n8yig/sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed
+--- sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed 1970-01-01 01:00:00.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed 2007-03-08 16:42:22.000000000 +0100
+@@ -0,0 +1,66 @@
++patching file perl/imap/IMAP/Shell.pm
++Hunk #1 FAILED at 436.
++Hunk #2 FAILED at 449.
++Hunk #3 FAILED at 469.
++Hunk #4 succeeded at 795 with fuzz 2 (offset 18 lines).
++Hunk #5 FAILED at 820.
++4 out of 5 hunks FAILED -- saving rejects to file perl/imap/IMAP/Shell.pm.rej
++patching file perl/imap/IMAP.pm
++Hunk #1 FAILED at 196.
++Hunk #2 succeeded at 302 with fuzz 2 (offset 41 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/imap/IMAP.pm.rej
++patching file perl/imap/IMAP.xs
++Hunk #1 FAILED at 57.
++Hunk #2 succeeded at 457 with fuzz 2 (offset 39 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/imap/IMAP.xs.rej
++patching file perl/imap/Makefile.PL
++Hunk #1 FAILED at 1.
++Hunk #2 FAILED at 65.
++2 out of 2 hunks FAILED -- saving rejects to file perl/imap/Makefile.PL.rej
++patching file perl/imap/cyradm.sh
++Hunk #1 FAILED at 54.
++1 out of 1 hunk FAILED -- saving rejects to file perl/imap/cyradm.sh.rej
++patching file perl/sieve/lib/isieve.c
++Hunk #1 succeeded at 47 with fuzz 2 (offset 2 lines).
++Hunk #2 succeeded at 72 with fuzz 2 (offset 11 lines).
++Hunk #3 FAILED at 103.
++Hunk #4 FAILED at 313.
++Hunk #5 succeeded at 430 with fuzz 1 (offset 54 lines).
++Hunk #6 succeeded at 702 with fuzz 2 (offset 58 lines).
++Hunk #7 FAILED at 867.
++3 out of 7 hunks FAILED -- saving rejects to file perl/sieve/lib/isieve.c.rej
++patching file perl/sieve/lib/isieve.h
++Hunk #1 FAILED at 67.
++1 out of 1 hunk FAILED -- saving rejects to file perl/sieve/lib/isieve.h.rej
++patching file perl/sieve/lib/request.c
++Hunk #1 FAILED at 168.
++Hunk #2 succeeded at 669 with fuzz 2 (offset 30 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/sieve/lib/request.c.rej
++patching file perl/sieve/lib/request.h
++Hunk #1 FAILED at 91.
++1 out of 1 hunk FAILED -- saving rejects to file perl/sieve/lib/request.h.rej
++patching file perl/sieve/managesieve/Makefile.PL
++Hunk #1 FAILED at 46.
++Hunk #2 FAILED at 62.
++2 out of 2 hunks FAILED -- saving rejects to file perl/sieve/managesieve/Makefile.PL.rej
++patching file perl/sieve/managesieve/managesieve.xs
++Hunk #1 FAILED at 211.
++Hunk #2 succeeded at 253 with fuzz 2 (offset 3 lines).
++Hunk #3 succeeded at 310 (offset 8 lines).
++1 out of 3 hunks FAILED -- saving rejects to file perl/sieve/managesieve/managesieve.xs.rej
++patching file perl/sieve/scripts/installsieve.pl
++Hunk #1 FAILED at 44.
++Hunk #2 FAILED at 56.
++Hunk #3 succeeded at 76 with fuzz 2 (offset 7 lines).
++Hunk #4 FAILED at 127.
++3 out of 4 hunks FAILED -- saving rejects to file perl/sieve/scripts/installsieve.pl.rej
++patching file perl/sieve/scripts/sieveshell.pl
++Hunk #1 FAILED at 61.
++Hunk #2 FAILED at 73.
++Hunk #3 succeeded at 96 with fuzz 2 (offset 8 lines).
++Hunk #4 FAILED at 172.
++Hunk #5 FAILED at 189.
++Hunk #6 FAILED at 334.
++Hunk #7 succeeded at 388 with fuzz 2 (offset 17 lines).
++5 out of 7 hunks FAILED -- saving rejects to file perl/sieve/scripts/sieveshell.pl.rej
++md5sum: 63d18aece91f37515327eaefdb6d24ae /tmp/dpep.9n8yig/sarge-2.2.13/debian/patches/66-cyradm-tls-enabled.dpatch
+diff -urNad sarge-2.2.13/perl/imap/IMAP/Shell.pm /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP/Shell.pm
+--- sarge-2.2.13/perl/imap/IMAP/Shell.pm 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP/Shell.pm 2007-03-08 16:42:22.306556343 +0100
+@@ -436,9 +436,10 @@
+ # (It's not as trivial as run() because it does things expected of standalone
+ # programs, as opposed to things expected from within a program.)
+ sub shell {
+- my ($server, $port, $authz, $auth, $systemrc, $userrc, $dorc, $mech, $pw) =
++ my ($server, $port, $authz, $auth, $systemrc, $userrc, $dorc, $mech, $pw,
++ $tlskey, $notls) =
+ ('', 143, undef, $ENV{USER} || $ENV{LOGNAME}, '/etc/cyradmrc.pl',
+- "$ENV{HOME}/.cyradmrc.pl", 1, undef, undef);
++ "$ENV{HOME}/.cyradmrc.pl", 1, undef, undef, "", undef);
+ GetOptions('user|u=s' => \$auth,
+ 'authz|z=s' => \$authz,
+ 'rc|r!' => \$dorc,
+@@ -448,6 +449,8 @@
+ 'port|p=i' => \$port,
+ 'auth|a=s' => \$mech,
+ 'password|w=s' => \$pw,
++ 'tlskey|t=s' => \$tlskey,
++ 'notls' => \$notls,
+ 'help|h' => sub { cyradm_usage(); exit(0); }
+ );
+ if ($server ne '' && @ARGV) {
+@@ -466,7 +469,8 @@
+ -callback => \&_cb_eof,
+ -rock => \$cyradm});
+ $cyradm->authenticate(-authz => $authz, -user => $auth,
+- -mechanism => $mech, -password => $pw)
++ -mechanism => $mech, -password => $pw,
++ -tlskey => $tlskey, -notls => $notls)
+ or die "cyradm: cannot authenticate to server" . (defined($mech)?" with $mech":"") . " as $auth\n";
+ }
+ my $fstk = [*STDIN, *STDOUT, *STDERR];
+@@ -773,6 +777,34 @@
+ $want = '-service';
+ next;
+ }
++ if (Cyrus::IMAP::imclient_havetls()) {
++ if ($opt ne '' && '-tlskey' =~ /^\Q$opt/ || $opt eq '--tlskey') {
++ $want = '-tlskey';
++ next;
++ }
++ if ($opt ne '' && '-notls' =~ /^\Q$opt/ || $opt eq '--notls') {
++ $want = '-notls';
++ next;
++ }
++ if ($opt =~ /^-/) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ }
++ }
++ if (Cyrus::IMAP::imclient_havetls()) {
++ if ($opt ne '' && '-tlskey' =~ /^\Q$opt/ || $opt eq '--tlskey') {
++ $want = '-tlskey';
++ next;
++ }
++ if ($opt ne '' && '-notls' =~ /^\Q$opt/ || $opt eq '--notls') {
++ $want = '-notls';
++ next;
++ }
++ if ($opt =~ /^-/) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ }
++ }
+ if ($opt =~ /^-/) {
+ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
+ " [-service name] [user]\n";
+@@ -784,8 +816,13 @@
+ }
+ push(@nargv, @argv);
+ if (@nargv > 1) {
+- die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
+- " [-service name] [user]\n";
++ if (Cyrus::IMAP::imclient_havetls()) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ } else {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [user]\n";
++ }
+ }
+ if (@nargv) {
+ $opts{-user} = shift(@nargv);
+diff -urNad sarge-2.2.13/perl/imap/IMAP.pm /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.pm
+--- sarge-2.2.13/perl/imap/IMAP.pm 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.pm 2007-03-08 16:42:22.307556244 +0100
+@@ -196,16 +196,43 @@
+ sub authenticate {
+ my ($self, $first) = @_;
+ my (%opts, $rc);
++ my ($starttls, $logindisabled) = (0, 0);
+
+ if (defined $first &&
+- $first =~ /^-\w+|Mechanism|Service|Authz|User|Minssf|Maxssf|Password$/) {
++ $first =~ /^-\w+|Mechanism|Service|Authz|User|Minssf|Maxssf|Password|Tlskey|Notls|CAfile|CApath$/) {
+ (undef, %opts) = @_;
+- foreach (qw(mechanism service authz user minssf maxssf password)) {
++ foreach (qw(mechanism service authz user minssf maxssf password tlskey notls)) {
+ $opts{'-' . $_} = $opts{ucfirst($_)} if !defined($opts{'-' . $_});
+ }
+ } else {
+ (undef, $opts{-mechanism}, $opts{-service}, $opts{-authz}, $opts{-user},
+- $opts{-minssf}, $opts{-maxssf}, $opts{-password}) = @_;
++ $opts{-minssf}, $opts{-maxssf}, $opts{-password},
++ $opts{-tlskey}, $opts{-notls}, $opts{-cafile}, $opts{-capath}) = @_;
++ }
++ if (havetls()) {
++ if (!defined($opts{-tlskey})) {
++ $opts{-tlskey} = "";
++ }
++ if (!defined($opts{-cafile})) {
++ $opts{-cafile} = "";
++ }
++ if (!defined($opts{-capath})) {
++ $opts{-capath} = "";
++ }
++ if ($opts{-notls}) {
++ $opts{-tlskey} = undef;
++ }
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $starttls = 1
++ if /^STARTTLS$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($starttls && defined($opts{-tlskey})) {
++ $self->_starttls($opts{-tlskey}, $opts{-tlskey}, $opts{-cafile}, $opts{-capath});
++ }
+ }
+ if (!defined($opts{-mechanism})) {
+ $opts{-mechanism} = '';
+@@ -234,6 +261,34 @@
+ $opts{-authz}, $opts{-user}, $opts{-password},
+ $opts{-minssf}, $opts{-maxssf});
+ }
++ if (!$rc) {
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $logindisabled = 1
++ if /^LOGINDISABLED$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($logindisabled) {
++ warn "Login disabled.\n";
++ return undef;
++ }
++ }
++ if (!$rc) {
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $logindisabled = 1
++ if /^LOGINDISABLED$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($logindisabled) {
++ warn "Login disabled.\n";
++ return undef;
++ }
++ }
+ $opts{-mechanism} ||= 'plain';
+ if (!$rc && $opts{-mechanism} =~ /(\b|^)(plain|login)($|\b)/i) {
+ $opts{-user} = getlogin if !defined($opts{-user});
+diff -urNad sarge-2.2.13/perl/imap/IMAP.xs /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.xs
+--- sarge-2.2.13/perl/imap/IMAP.xs 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.xs 2007-03-08 16:42:22.308556145 +0100
+@@ -57,6 +57,7 @@
+ #include "xmalloc.h"
+
+ #include "cyrperl.h"
++#include "config.h"
+
+ typedef struct xscyrus *Cyrus_IMAP;
+
+@@ -417,6 +418,82 @@
+ ST(0) = &sv_yes;
+ }
+
++int
++imclient_havetls()
++CODE:
++#ifdef HAVE_SSL
++ RETVAL = 1;
++#else
++ RETVAL = 0;
++#endif /* HAVE_SSL */
++OUTPUT:
++ RETVAL
++
++SV *
++imclient__starttls(client, tls_cert_file, tls_key_file, CAfile, CApath)
++ Cyrus_IMAP client
++ char* tls_cert_file
++ char* tls_key_file
++ char* CAfile
++ char* CApath
++PREINIT:
++ int rc;
++ int tls_layer;
++CODE:
++ ST(0) = sv_newmortal();
++
++ /* If the tls_{cert, key}_file parameters are undef, set to be NULL */
++ if(!SvOK(ST(2))) tls_cert_file = NULL;
++ if(!SvOK(ST(3))) tls_key_file = NULL;
++#ifdef HAVE_SSL
++ rc = imclient_starttls(client->imclient, tls_cert_file, tls_key_file, CAfile, CApath);
++ if (rc)
++ ST(0) = &sv_no;
++ else {
++ ST(0) = &sv_yes;
++ }
++#else
++ ST(0) = &sv_no;
++#endif /* HAVE_SSL */
++
++int
++imclient_havetls()
++CODE:
++#ifdef HAVE_SSL
++ RETVAL = 1;
++#else
++ RETVAL = 0;
++#endif /* HAVE_SSL */
++OUTPUT:
++ RETVAL
++
++SV *
++imclient__starttls(client, tls_cert_file, tls_key_file, CAfile, CApath)
++ Cyrus_IMAP client
++ char* tls_cert_file
++ char* tls_key_file
++ char* CAfile
++ char* CApath
++PREINIT:
++ int rc;
++ int tls_layer;
++CODE:
++ ST(0) = sv_newmortal();
++
++ /* If the tls_{cert, key}_file parameters are undef, set to be NULL */
++ if(!SvOK(ST(2))) tls_cert_file = NULL;
++ if(!SvOK(ST(3))) tls_key_file = NULL;
++#ifdef HAVE_SSL
++ rc = imclient_starttls(client->imclient, tls_cert_file, tls_key_file, CAfile, CApath);
++ if (rc)
++ ST(0) = &sv_no;
++ else {
++ ST(0) = &sv_yes;
++ }
++#else
++ ST(0) = &sv_no;
++#endif /* HAVE_SSL */
++
+ void
+ imclient_addcallback(client, ...)
+ Cyrus_IMAP client
+diff -urNad sarge-2.2.13/perl/imap/Makefile.PL /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/Makefile.PL
+--- sarge-2.2.13/perl/imap/Makefile.PL 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/Makefile.PL 2007-03-08 16:42:22.308556145 +0100
+@@ -1,5 +1,4 @@
+ #
+-# Copyright (c) 2000 Carnegie Mellon University. All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+@@ -66,7 +65,7 @@
+ 'OBJECT' => 'IMAP.o',
+ 'MYEXTLIB' => '../../lib/libcyrus.a ../../lib/libcyrus_min.a',
+ 'LIBS' => ["$BDB_LIB $SASL_LIB $OPENSSL_LIB $LIB_RT -lssl -lcrypto"],
+- 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
+- 'INC' => "-I../../lib $SASL_INC $OPENSSL_INC",
++ 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
++ 'INC' => "-I../../lib -I../.. $SASL_INC $OPENSSL_INC",
+ 'EXE_FILES' => [cyradm],
+ );
+diff -urNad sarge-2.2.13/perl/imap/cyradm.sh /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/cyradm.sh
+--- sarge-2.2.13/perl/imap/cyradm.sh 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/cyradm.sh 2007-03-08 16:42:22.309556046 +0100
+@@ -54,7 +54,8 @@
+ =head1 SYNOPSIS
+
+ $ cyradm [--user user] [--[no]rc] [--systemrc file] [--userrc file] \
+- > [--port n] [--auth mechanism] [--server] server
++ > [--port n] [--auth mechanism] [--tlskey keyfile] [--notls] \
++ > [--server] server
+
+ but possibly
+
+diff -urNad sarge-2.2.13/perl/sieve/lib/isieve.c /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.c
+--- sarge-2.2.13/perl/sieve/lib/isieve.c 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.c 2007-03-08 16:42:22.311555847 +0100
+@@ -45,6 +45,10 @@
+ #include <config.h>
+ #endif
+
++#include <assert.h>
++
++#include <assert.h>
++
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+@@ -59,6 +63,24 @@
+ #include <sasl/sasl.h>
+ #include <sasl/saslutil.h>
+
++#ifdef HAVE_SSL
++#include <openssl/lhash.h>
++#include <openssl/bn.h>
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/x509.h>
++#include <openssl/ssl.h>
++#endif /* HAVE_SSL */
++
++#ifdef HAVE_SSL
++#include <openssl/lhash.h>
++#include <openssl/bn.h>
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/x509.h>
++#include <openssl/ssl.h>
++#endif /* HAVE_SSL */
++
+ #include "isieve.h"
+ #include "lex.h"
+ #include "request.h"
+@@ -81,13 +103,27 @@
+ sasl_callback_t *refer_callbacks;
+
+ int version;
++ int starttls;
++ char *tls_keyfile;
+
+ struct protstream *pin;
+ struct protstream *pout;
++
++#ifdef HAVE_SSL
++ SSL_CTX *tls_ctx;
++ SSL *tls_conn;
++#endif /* HAVE_SSL */
+ };
+
+ void fillin_interactions(sasl_interact_t *tlist);
+
++#ifdef HAVE_SSL
++static int isieve_starttls(isieve_t *obj, int verifydepth,
++ char *var_tls_cert_file, char *var_tls_key_file,
++ int *layer);
++#endif /* HAVE_SSL */
++
++
+ /* we need this separate from the free() call so that we can reuse
+ * the same memory for referrals */
+ static void sieve_dispose(isieve_t *obj)
+@@ -277,7 +313,7 @@
+ } else if (strcasecmp(attr,"IMPLEMENTATION")==0) {
+
+ } else if (strcasecmp(attr,"STARTTLS")==0) {
+- /* TODO */
++ obj->starttls = 1;
+ } else if (val && strncmp(val,"SASL=",5)==0) {
+ obj->version = OLD_VERSION;
+ cap = (char *) xmalloc(strlen(val));
+@@ -351,6 +387,64 @@
+ return STAT_CONT;
+ }
+
++int auth_starttls(isieve_t *obj, char *tls_keyfile,
++ char **mechlist, char **errstr)
++{
++ unsigned ext_ssf = 0;
++ int ret;
++ char *refer_to;
++
++ if (!obj->tls_keyfile) obj->tls_keyfile = tls_keyfile;
++
++ if (!obj->starttls || !obj->tls_keyfile) return 0;
++
++#ifdef HAVE_SSL
++ ret = starttls(obj->version, obj->pout, obj->pin, &refer_to, errstr);
++ /* xxx handle referrals */
++ if (ret != 0) return -1;
++
++ ret = isieve_starttls(obj, 0, tls_keyfile, tls_keyfile, &ext_ssf);
++ if (ret != 0) return -1;
++
++ prot_printf(obj->pout, "CAPABILITY\r\n");
++ prot_flush(obj->pout);
++
++ if (*mechlist) free(*mechlist);
++ *mechlist = read_capability(obj);
++#endif /* HAVE_SSL */
++
++ return 0;
++}
++
++int auth_starttls(isieve_t *obj, char *tls_keyfile,
++ char **mechlist, char **errstr)
++{
++ unsigned ext_ssf = 0;
++ int ret;
++ char *refer_to;
++
++ if (!obj->tls_keyfile) obj->tls_keyfile = tls_keyfile;
++
++ if (!obj->starttls || !obj->tls_keyfile) return 0;
++
++#ifdef HAVE_SSL
++ ret = starttls(obj->version, obj->pout, obj->pin, &refer_to, errstr);
++ /* xxx handle referrals */
++ if (ret != 0) return -1;
++
++ ret = isieve_starttls(obj, 0, tls_keyfile, tls_keyfile, &ext_ssf);
++ if (ret != 0) return -1;
++
++ prot_printf(obj->pout, "CAPABILITY\r\n");
++ prot_flush(obj->pout);
++
++ if (*mechlist) free(*mechlist);
++ *mechlist = read_capability(obj);
++#endif /* HAVE_SSL */
++
++ return 0;
++}
++
+
+ int auth_sasl(char *mechlist, isieve_t *obj, const char **mechusing,
+ char **errstr)
+@@ -590,6 +684,14 @@
+ /* Authenticate */
+ mechlist = read_capability(obj_new);
+
++ /* Perform STARTTLS */
++ ret = auth_starttls(obj, obj->tls_keyfile, &mechlist, &errstr);
++ if (ret) return STAT_NO;
++
++ /* Perform STARTTLS */
++ ret = auth_starttls(obj, obj->tls_keyfile, &mechlist, &errstr);
++ if (ret) return STAT_NO;
++
+ do {
+ mtried = NULL;
+ ret = auth_sasl(mechlist, obj_new, &mtried, &errstr);
+@@ -751,3 +853,342 @@
+
+ return ret;
+ }
++
++/*************** All these functions help do the starttls; these are copied from imclient.c ********/
++#ifdef HAVE_SSL
++
++static int verify_depth;
++static int verify_error = X509_V_OK;
++
++#define CCERT_BUFSIZ 256
++static char peer_CN[CCERT_BUFSIZ];
++static char issuer_CN[CCERT_BUFSIZ];
++
++/*
++ * Set up the cert things on the server side. We do need both the
++ * private key (in key_file) and the cert (in cert_file).
++ * Both files may be identical.
++ *
++ * This function is taken from OpenSSL apps/s_cb.c
++ */
++
++static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
++{
++ if (cert_file != NULL) {
++ if (SSL_CTX_use_certificate_file(ctx, cert_file,
++ SSL_FILETYPE_PEM) <= 0) {
++ printf("[ unable to get certificate from '%s' ]\n", cert_file);
++ return (0);
++ }
++ if (key_file == NULL)
++ key_file = cert_file;
++ if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
++ SSL_FILETYPE_PEM) <= 0) {
++ printf("[ unable to get private key from '%s' ]\n", key_file);
++ return (0);
++ }
++ /* Now we know that a key and cert have been set against
++ * the SSL context */
++ if (!SSL_CTX_check_private_key(ctx)) {
++ printf("[ Private key does not match the certificate public key ]\n");
++ return (0);
++ }
++ }
++ return (1);
++}
++
++/* taken from OpenSSL apps/s_cb.c */
++
++static int verify_callback(int ok, X509_STORE_CTX * ctx)
++{
++ char buf[256];
++ X509 *err_cert;
++ int err;
++ int depth;
++
++ err_cert = X509_STORE_CTX_get_current_cert(ctx);
++ err = X509_STORE_CTX_get_error(ctx);
++ depth = X509_STORE_CTX_get_error_depth(ctx);
++
++ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
++
++ /* if (verbose==1)
++ printf("Peer cert verify depth=%d %s\n", depth, buf);*/
++
++ if (!ok) {
++ printf("verify error:num=%d:%s\n", err,
++ X509_verify_cert_error_string(err));
++ if (verify_depth >= depth) {
++ ok = 1;
++ verify_error = X509_V_OK;
++ } else {
++ ok = 0;
++ verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
++ }
++ }
++ switch (ctx->error) {
++ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
++ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
++ printf("issuer= %s\n", buf);
++ break;
++ case X509_V_ERR_CERT_NOT_YET_VALID:
++ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
++ printf("cert not yet valid\n");
++ break;
++ case X509_V_ERR_CERT_HAS_EXPIRED:
++ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
++ printf("cert has expired\n");
++ break;
++ }
++
++ /* if (verbose==1)
++ printf("verify return:%d\n", ok);*/
++
++ return (ok);
++}
++
++
++/* taken from OpenSSL apps/s_cb.c */
++static RSA *tmp_rsa_cb(SSL *s __attribute__((unused)),
++ int export __attribute__((unused)),
++ int keylength)
++{
++ static RSA *rsa_tmp = NULL;
++
++ if (rsa_tmp == NULL) {
++ rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
++ }
++ return (rsa_tmp);
++}
++
++/*
++ * Seed the random number generator.
++ */
++static int tls_rand_init(void)
++{
++#ifdef EGD_SOCKET
++ return (RAND_egd(EGD_SOCKET));
++#else
++ /* otherwise let OpenSSL do it internally */
++ return 0;
++#endif
++}
++
++static char *var_tls_CAfile="";
++static char *var_tls_CApath="";
++ /*
++ * This is the setup routine for the SSL client.
++ *
++ * The skeleton of this function is taken from OpenSSL apps/s_client.c.
++ */
++
++static int tls_init_clientengine(isieve_t *obj,
++ int verifydepth, char *var_tls_cert_file, char *var_tls_key_file)
++{
++ int off = 0;
++ int verify_flags = SSL_VERIFY_NONE;
++ char *CApath;
++ char *CAfile;
++ char *c_cert_file;
++ char *c_key_file;
++
++ assert(obj);
++
++ SSL_load_error_strings();
++ SSLeay_add_ssl_algorithms();
++ if (tls_rand_init() == -1) {
++ printf("[ TLS engine: cannot seed PRNG ]\n");
++ return -1;
++ }
++
++ obj->tls_ctx = SSL_CTX_new(TLSv1_client_method());
++ if (obj->tls_ctx == NULL) {
++ return -1;
++ };
++
++ off |= SSL_OP_ALL; /* Work around all known bugs */
++ SSL_CTX_set_options(obj->tls_ctx, off);
++
++ /* debugging SSL_CTX_set_info_callback(obj->tls_ctx, apps_ssl_info_callback); */
++
++ if (strlen(var_tls_CAfile) == 0)
++ CAfile = NULL;
++ else
++ CAfile = var_tls_CAfile;
++ if (strlen(var_tls_CApath) == 0)
++ CApath = NULL;
++ else
++ CApath = var_tls_CApath;
++
++ if (CAfile || CApath)
++ if ((!SSL_CTX_load_verify_locations(obj->tls_ctx, CAfile, CApath)) ||
++ (!SSL_CTX_set_default_verify_paths(obj->tls_ctx))) {
++ printf("[ TLS engine: cannot load CA data ]\n");
++ return -1;
++ }
++ if (strlen(var_tls_cert_file) == 0)
++ c_cert_file = NULL;
++ else
++ c_cert_file = var_tls_cert_file;
++ if (strlen(var_tls_key_file) == 0)
++ c_key_file = NULL;
++ else
++ c_key_file = var_tls_key_file;
++
++ if (c_cert_file || c_key_file)
++ if (!set_cert_stuff(obj->tls_ctx, c_cert_file, c_key_file)) {
++ printf("[ TLS engine: cannot load cert/key data ]\n");
++ return -1;
++ }
++ SSL_CTX_set_tmp_rsa_callback(obj->tls_ctx, tmp_rsa_cb);
++
++ verify_depth = verifydepth;
++ SSL_CTX_set_verify(obj->tls_ctx, verify_flags, verify_callback);
++
++ return 0;
++}
++
++
++static int tls_start_clienttls(isieve_t *obj,
++ unsigned *layer, char **authid, int fd)
++{
++ int sts;
++ SSL_SESSION *session;
++ SSL_CIPHER *cipher;
++ X509 *peer;
++ const char *tls_protocol = NULL;
++ const char *tls_cipher_name = NULL;
++ int tls_cipher_usebits = 0;
++ int tls_cipher_algbits = 0;
++ char *tls_peer_CN = "";
++ char *tls_issuer_CN = NULL;
++
++ if (obj->tls_conn == NULL) {
++ obj->tls_conn = (SSL *) SSL_new(obj->tls_ctx);
++ }
++ if (obj->tls_conn == NULL) {
++ printf("Could not allocate 'con' with SSL_new()\n");
++ return -1;
++ }
++ SSL_clear(obj->tls_conn);
++
++ if (!SSL_set_fd(obj->tls_conn, fd)) {
++ printf("SSL_set_fd failed\n");
++ return -1;
++ }
++
++ /*SSL_set_read_ahead(obj->tls_conn, 1);*/
++
++ /*
++ * This is the actual handshake routine. It will do all the negotiations
++ * and will check the client cert etc.
++ */
++ SSL_set_connect_state(obj->tls_conn);
++
++
++ /*
++ * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
++ * Well there is a BIO below the SSL routines that is automatically
++ * created for us, so we can use it for debugging purposes.
++ */
++ /* if (verbose==1) */
++ /* BIO_set_callback(SSL_get_rbio(obj->tls_conn), bio_dump_cb);*/
++
++ /* Dump the negotiation for loglevels 3 and 4 */
++
++ if ((sts = SSL_connect(obj->tls_conn)) <= 0) {
++ printf("[ SSL_connect error %d ]\n", sts); /* xxx get string error? */
++ session = SSL_get_session(obj->tls_conn);
++ if (session) {
++ SSL_CTX_remove_session(obj->tls_ctx, session);
++ printf("[ SSL session removed ]\n");
++ }
++ if (obj->tls_conn!=NULL)
++ SSL_free(obj->tls_conn);
++ obj->tls_conn = NULL;
++ return -1;
++ }
++
++ /*
++ * Lets see, whether a peer certificate is availabe and what is
++ * the actual information. We want to save it for later use.
++ */
++ peer = SSL_get_peer_certificate(obj->tls_conn);
++ if (peer != NULL) {
++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
++ NID_commonName, peer_CN, CCERT_BUFSIZ);
++ tls_peer_CN = peer_CN;
++ X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
++ NID_commonName, issuer_CN, CCERT_BUFSIZ);
++ /* if (verbose==1)
++ printf("subject_CN=%s, issuer_CN=%s\n", peer_CN, issuer_CN);*/
++ tls_issuer_CN = issuer_CN;
++
++ }
++ tls_protocol = SSL_get_version(obj->tls_conn);
++ cipher = SSL_get_current_cipher(obj->tls_conn);
++ tls_cipher_name = SSL_CIPHER_get_name(cipher);
++ tls_cipher_usebits = SSL_CIPHER_get_bits(cipher,
++ &tls_cipher_algbits);
++
++ if (layer!=NULL)
++ *layer = tls_cipher_usebits;
++
++ if (authid!=NULL)
++ *authid = tls_peer_CN;
++
++ /* printf("TLS connection established: %s with cipher %s (%d/%d bits)\n",
++ tls_protocol, tls_cipher_name,
++ tls_cipher_usebits, tls_cipher_algbits);*/
++ return 0;
++}
++
++static int isieve_starttls(isieve_t *obj,
++ int verifydepth __attribute__((unused)),
++ char *var_tls_cert_file,
++ char *var_tls_key_file,
++ int *layer __attribute__((unused)))
++{
++ int result;
++ unsigned ssf;
++ char *auth_id;
++
++ result=tls_init_clientengine(obj, 10, var_tls_cert_file, var_tls_key_file);
++ if (result!=0)
++ {
++ printf("[ TLS engine failed ]\n");
++ return 1;
++ } else {
++ result=tls_start_clienttls(obj, &ssf, &auth_id, obj->sock);
++
++ if (result!=0) {
++ printf("[ TLS negotiation did not succeed ]\n");
++ return 1;
++ }
++ }
++
++ /* turn non-blocking i/o back on */
++
++
++ /* TLS negotiation succeeded */
++
++ auth_id=""; /* xxx this really should be peer_CN or
++ issuer_CN but I can't figure out which is
++ which at the moment */
++
++ /* tell SASL about the negotiated layer */
++ result=sasl_setprop(obj->conn,
++ SASL_SSF_EXTERNAL,
++ &ssf);
++ if (result!=SASL_OK) return 1;
++ result=sasl_setprop(obj->conn,
++ SASL_AUTH_EXTERNAL,
++ auth_id);
++ if (result!=SASL_OK) return 1;
++
++ prot_settls (obj->pin, obj->tls_conn);
++ prot_settls (obj->pout, obj->tls_conn);
++
++ return 0;
++}
++#endif /* HAVE_SSL */
+diff -urNad sarge-2.2.13/perl/sieve/lib/isieve.h /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.h
+--- sarge-2.2.13/perl/sieve/lib/isieve.h 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.h 2007-03-08 16:42:22.312555748 +0100
+@@ -67,6 +67,7 @@
+ STAT_OK = 2
+ } imt_stat;
+
++int auth_starttls(isieve_t *obj, char *tls_keyfile, char **mechlist, char **errstr);
+ int auth_sasl(char *mechlist, isieve_t *obj, const char **mechusing, char **errstr);
+
+ int isieve_logout(isieve_t **obj);
+diff -urNad sarge-2.2.13/perl/sieve/lib/request.c /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.c
+--- sarge-2.2.13/perl/sieve/lib/request.c 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.c 2007-03-08 16:42:22.313555649 +0100
+@@ -168,22 +168,24 @@
+ /* SASL response */
+ res = yylex(&state, pin);
+ if(res == ' ') {
+- if (yylex(&state, pin) != '(')
+- parseerror("expected LPAREN");
+-
+- if (yylex(&state, pin)==TOKEN_SASL) {
+- if (yylex(&state, pin)!=' ')
+- parseerror("expected space");
+- if (yylex(&state, pin)!=STRING)
+- parseerror("expected string");
++ res = yylex(&state, pin);
++ if (res == '(') {
++ if (yylex(&state, pin)==TOKEN_SASL) {
++ if (yylex(&state, pin)!=' ')
++ parseerror("expected space");
++ if (yylex(&state, pin)!=STRING)
++ parseerror("expected string");
+
+- *refer_to = xstrdup(string_DATAPTR(state.str));
++ *refer_to = xstrdup(string_DATAPTR(state.str));
+
+- if (yylex(&state, pin)!=')')
+- parseerror("expected RPAREN");
+- } else {
+- parseerror("unexpected response code with OK response");
++ if (yylex(&state, pin) != ')')
++ parseerror("expected RPAREN");
++ res = yylex(&state, pin);
++ if (res == ' ') res = yylex(&state, pin);
++ }
+ }
++ if (res != STRING)
++ parseerror("unexpected response code with OK response");
+ } else if (version != OLD_VERSION && res == EOL) {
+ return r;
+ }
+@@ -637,3 +639,59 @@
+ return 0;
+
+ }
++
++
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstrp)
++{
++ lexstate_t state;
++ int res;
++ int ret;
++ mystring_t *errstr;
++
++ prot_printf(pout, "STARTTLS\r\n");
++ prot_flush(pout);
++
++ res = yylex(&state, pin);
++
++ ret = handle_response(res, version, pin, refer_to, &errstr);
++
++ /* if command failed */
++ if(ret == -2 && *refer_to) {
++ return -2;
++ } else if (ret != 0) {
++ *errstrp = malloc(128);
++ snprintf(*errstrp, 127,
++ "Starttls: %s",string_DATAPTR(errstr));
++ return -1;
++ }
++ return 0;
++}
++
++
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstrp)
++{
++ lexstate_t state;
++ int res;
++ int ret;
++ mystring_t *errstr;
++
++ prot_printf(pout, "STARTTLS\r\n");
++ prot_flush(pout);
++
++ res = yylex(&state, pin);
++
++ ret = handle_response(res, version, pin, refer_to, &errstr);
++
++ /* if command failed */
++ if(ret == -2 && *refer_to) {
++ return -2;
++ } else if (ret != 0) {
++ *errstrp = malloc(128);
++ snprintf(*errstrp, 127,
++ "Starttls: %s",string_DATAPTR(errstr));
++ return -1;
++ }
++ return 0;
++}
+diff -urNad sarge-2.2.13/perl/sieve/lib/request.h /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.h
+--- sarge-2.2.13/perl/sieve/lib/request.h 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.h 2007-03-08 16:42:22.313555649 +0100
+@@ -91,5 +91,7 @@
+
+ void parseerror(char *str);
+
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstr);
+
+ #endif
+diff -urNad sarge-2.2.13/perl/sieve/managesieve/Makefile.PL /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/Makefile.PL
+--- sarge-2.2.13/perl/sieve/managesieve/Makefile.PL 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/Makefile.PL 2007-03-08 16:42:22.313555649 +0100
+@@ -46,6 +46,7 @@
+ my $SASL_LIB = $ENV{SASL_LIB} || "-lsasl2";
+ my $OPENSSL_INC = $ENV{OPENSSL_INC};
+ my $OPENSSL_LIB = $ENV{OPENSSL_LIB};
++my $HAVE_SSL = $OPENSSL_LIB ? "-DHAVE_SSL" : '';
+ my $BDB_INC = $ENV{BDB_INC};
+ my $BDB_LIB = $ENV{BDB_LIB};
+
+@@ -61,7 +62,7 @@
+ 'VERSION_FROM' => 'managesieve.pm', # finds $VERSION
+ 'MYEXTLIB' => '../lib/isieve.o ../lib/lex.o ../lib/mystring.o ../lib/request.o ../../../lib/libcyrus.a ../../../lib/libcyrus_min.a',
+ 'LIBS' => ["$BDB_LIB $SASL_LIB $OPENSSL_LIB $LIB_RT -lssl -lcrypto"],
+- 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
++ 'DEFINE' => "-DPERL_POLLUTE $HAVE_SSL", # e.g., '-DHAVE_SOMETHING'
+ 'INC' => "-I../lib/ -I../../../lib/ $SASL_INC $OPENSSL_INC",
+ 'CC' => $ENV{CC},
+ 'LD' => $ENV{CC}
+diff -urNad sarge-2.2.13/perl/sieve/managesieve/managesieve.xs /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/managesieve.xs
+--- sarge-2.2.13/perl/sieve/managesieve/managesieve.xs 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/managesieve.xs 2007-03-08 16:42:22.314555550 +0100
+@@ -211,12 +211,13 @@
+
+
+ Sieveobj
+-sieve_get_handle(servername, username_cb, authname_cb, password_cb, realm_cb)
++sieve_get_handle(servername, username_cb, authname_cb, password_cb, realm_cb, tls_keyfile)
+ char *servername
+ SV *username_cb
+ SV *authname_cb
+ SV *password_cb
+ SV *realm_cb
++ char *tls_keyfile
+
+ PREINIT:
+ Sieveobj ret = NULL;
+@@ -249,6 +250,10 @@
+ callbacks[3].context = password_cb;
+ callbacks[4].id = SASL_CB_LIST_END;
+
++ if (!SvOK(ST(5))) tls_keyfile = NULL;
++
++ if (!SvOK(ST(5))) tls_keyfile = NULL;
++
+ /* see if we have server:port (or IPv6, etc)*/
+ p = servername;
+ if (*servername == '[') {
+@@ -299,6 +304,16 @@
+ XSRETURN_UNDEF;
+ }
+
++ if (auth_starttls(obj, tls_keyfile, &mlist, &ret->errstr) != 0) {
++ globalerr = "starttls failed";
++ XSRETURN_UNDEF;
++ }
++
++ if (auth_starttls(obj, tls_keyfile, &mlist, &ret->errstr) != 0) {
++ globalerr = "starttls failed";
++ XSRETURN_UNDEF;
++ }
++
+ /* loop through all the mechanisms */
+ do {
+ mtried = NULL;
+diff -urNad sarge-2.2.13/perl/sieve/scripts/installsieve.pl /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/installsieve.pl
+--- sarge-2.2.13/perl/sieve/scripts/installsieve.pl 2007-03-08 16:40:29.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/installsieve.pl 2007-03-08 16:42:22.315555451 +0100
+@@ -44,6 +44,7 @@
+ use Getopt::Long;
+
+ $username = "";
++$tls_keyfile = "";
+
+ print "NOTE: This program is deprecated. Please use sieveshell\n";
+ print "\n";
+@@ -55,6 +56,8 @@
+ "a|activates:s" => \$activates,
+ "d|deletes:s" => \$deletes,
+ # "m|mechanism:s" => \$mech,
++ "t|tlskey:s" => \$tls_keyfile,
++ "n|notls" => \$notls,
+ "g|gets:s" => \$gets,
+ "u|username:s" => \$username,
+ # "w|password:s" => \$pass
+@@ -66,6 +69,14 @@
+
+ $acapserver = $ARGV[0];
+
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
+ sub list_cb {
+
+ my($name, $isactive) = @_ ;
+@@ -113,11 +124,13 @@
+ print " -g <name> Get script <name> and save to disk\n";
+ print " -u <user> Userid/Authname to use\n";
+ # print " -w <passwd> Specify password (Should only be used for automated scripts)\n";
++ print " -t <keyfile> TLS keyfile to use\n";
++ print " -n Don't use TLS\n";
+ print "\n";
+ }
+
+ #main code
+-my $obj = sieve_get_handle($acapserver,"prompt","prompt","prompt","prompt");
++my $obj = sieve_get_handle($acapserver,"prompt","prompt","prompt","prompt", $tls_keyfile);
+
+ if (!defined $obj) {
+ die "Unable to connect to server";
+diff -urNad sarge-2.2.13/perl/sieve/scripts/sieveshell.pl /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/sieveshell.pl
+--- sarge-2.2.13/perl/sieve/scripts/sieveshell.pl 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/sieveshell.pl 2007-03-08 16:42:22.316555352 +0100
+@@ -61,6 +61,8 @@
+ my $authname = $ENV{USER};
+ my $realm = "";
+ my $password;
++my $tls_keyfile = "";
++my $notls = 0;
+ my $ex = "";
+ my $exfile = "";
+ my $help = 0;
+@@ -71,6 +73,8 @@
+ "u|username:s" => \$username,
+ "r|realm:s" => \$realm,
+ "p|password:s" => \$password,
++ "t|tlskey:s" => \$tls_keyfile,
++ "n|notls" => \$notls,
+ "e|exec:s" => \$ex,
+ "f|execfile:s" => \$exfile,
+ "help|?" => \$help,
+@@ -84,6 +88,14 @@
+
+ my $acapserver = $ARGV[0];
+
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
+ my $filehandle;
+ my $interactive;
+
+@@ -156,7 +168,7 @@
+
+ sub show_help {
+ print "Usage:\n";
+- print " sieveshell [-u username] [-a authname] [-r realm] <server>\n";
++ print " sieveshell [-u username] [-a authname] [-r realm] [-t keyfile] [-n] <server>\n";
+ print "\n";
+ print "help - this screen\n";
+ print "list - list scripts on server\n";
+@@ -173,7 +185,7 @@
+ print "connecting to $acapserver\n";
+
+ my $obj = sieve_get_handle($acapserver,
+- "prompt", "prompt", "prompt", "prompt");
++ "prompt", "prompt", "prompt", "prompt", $tls_keyfile);
+
+ if (!defined $obj) {
+ die "unable to connect to server";
+@@ -318,6 +330,7 @@
+
+ sieveshell [B<--user>=I<user>] [B<--authname>=I<authname>]
+ [B<--realm>=I<realm>] [B<--password>=I<password>]
++[B<--tlskey>=I<keyfile>] [B<--notls>]
+ [B<--exec>=I<script>] [B<--execfile>=I<file>] I<server>[B<:>I<port>]
+
+ sieveshell B<--help>
+@@ -362,6 +375,22 @@
+
+ The realm to attempt authentication in.
+
++=item B<-t> I<keyfile>, B<--tlskey>=I<keyfile>
++
++I<keyfile> contains the TLS public and private keys to use.
++
++=item B<-n>, B<--notls>
++
++Disable TLS.
++
++=item B<-t> I<keyfile>, B<--tlskey>=I<keyfile>
++
++I<keyfile> contains the TLS public and private keys to use.
++
++=item B<-n>, B<--notls>
++
++Disable TLS.
++
+ =item B<-p> I<password>, B<--password>=I<password>
+
+ The password to use when authenticating to server. Note that this
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## fileUtqrG1.dpatch by Sven Mueller <sven at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed /tmp/dpep.9n8yig/sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed
+--- sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed 1970-01-01 01:00:00.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/debian/patched/66-cyradm-tls-enabled.dpatch.failed 2007-03-08 16:42:22.000000000 +0100
+@@ -0,0 +1,66 @@
++patching file perl/imap/IMAP/Shell.pm
++Hunk #1 FAILED at 436.
++Hunk #2 FAILED at 449.
++Hunk #3 FAILED at 469.
++Hunk #4 succeeded at 795 with fuzz 2 (offset 18 lines).
++Hunk #5 FAILED at 820.
++4 out of 5 hunks FAILED -- saving rejects to file perl/imap/IMAP/Shell.pm.rej
++patching file perl/imap/IMAP.pm
++Hunk #1 FAILED at 196.
++Hunk #2 succeeded at 302 with fuzz 2 (offset 41 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/imap/IMAP.pm.rej
++patching file perl/imap/IMAP.xs
++Hunk #1 FAILED at 57.
++Hunk #2 succeeded at 457 with fuzz 2 (offset 39 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/imap/IMAP.xs.rej
++patching file perl/imap/Makefile.PL
++Hunk #1 FAILED at 1.
++Hunk #2 FAILED at 65.
++2 out of 2 hunks FAILED -- saving rejects to file perl/imap/Makefile.PL.rej
++patching file perl/imap/cyradm.sh
++Hunk #1 FAILED at 54.
++1 out of 1 hunk FAILED -- saving rejects to file perl/imap/cyradm.sh.rej
++patching file perl/sieve/lib/isieve.c
++Hunk #1 succeeded at 47 with fuzz 2 (offset 2 lines).
++Hunk #2 succeeded at 72 with fuzz 2 (offset 11 lines).
++Hunk #3 FAILED at 103.
++Hunk #4 FAILED at 313.
++Hunk #5 succeeded at 430 with fuzz 1 (offset 54 lines).
++Hunk #6 succeeded at 702 with fuzz 2 (offset 58 lines).
++Hunk #7 FAILED at 867.
++3 out of 7 hunks FAILED -- saving rejects to file perl/sieve/lib/isieve.c.rej
++patching file perl/sieve/lib/isieve.h
++Hunk #1 FAILED at 67.
++1 out of 1 hunk FAILED -- saving rejects to file perl/sieve/lib/isieve.h.rej
++patching file perl/sieve/lib/request.c
++Hunk #1 FAILED at 168.
++Hunk #2 succeeded at 669 with fuzz 2 (offset 30 lines).
++1 out of 2 hunks FAILED -- saving rejects to file perl/sieve/lib/request.c.rej
++patching file perl/sieve/lib/request.h
++Hunk #1 FAILED at 91.
++1 out of 1 hunk FAILED -- saving rejects to file perl/sieve/lib/request.h.rej
++patching file perl/sieve/managesieve/Makefile.PL
++Hunk #1 FAILED at 46.
++Hunk #2 FAILED at 62.
++2 out of 2 hunks FAILED -- saving rejects to file perl/sieve/managesieve/Makefile.PL.rej
++patching file perl/sieve/managesieve/managesieve.xs
++Hunk #1 FAILED at 211.
++Hunk #2 succeeded at 253 with fuzz 2 (offset 3 lines).
++Hunk #3 succeeded at 310 (offset 8 lines).
++1 out of 3 hunks FAILED -- saving rejects to file perl/sieve/managesieve/managesieve.xs.rej
++patching file perl/sieve/scripts/installsieve.pl
++Hunk #1 FAILED at 44.
++Hunk #2 FAILED at 56.
++Hunk #3 succeeded at 76 with fuzz 2 (offset 7 lines).
++Hunk #4 FAILED at 127.
++3 out of 4 hunks FAILED -- saving rejects to file perl/sieve/scripts/installsieve.pl.rej
++patching file perl/sieve/scripts/sieveshell.pl
++Hunk #1 FAILED at 61.
++Hunk #2 FAILED at 73.
++Hunk #3 succeeded at 96 with fuzz 2 (offset 8 lines).
++Hunk #4 FAILED at 172.
++Hunk #5 FAILED at 189.
++Hunk #6 FAILED at 334.
++Hunk #7 succeeded at 388 with fuzz 2 (offset 17 lines).
++5 out of 7 hunks FAILED -- saving rejects to file perl/sieve/scripts/sieveshell.pl.rej
++md5sum: 63d18aece91f37515327eaefdb6d24ae /tmp/dpep.9n8yig/sarge-2.2.13/debian/patches/66-cyradm-tls-enabled.dpatch
+diff -urNad sarge-2.2.13/perl/imap/IMAP/Shell.pm /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP/Shell.pm
+--- sarge-2.2.13/perl/imap/IMAP/Shell.pm 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP/Shell.pm 2007-03-08 16:42:22.306556343 +0100
+@@ -436,9 +436,10 @@
+ # (It's not as trivial as run() because it does things expected of standalone
+ # programs, as opposed to things expected from within a program.)
+ sub shell {
+- my ($server, $port, $authz, $auth, $systemrc, $userrc, $dorc, $mech, $pw) =
++ my ($server, $port, $authz, $auth, $systemrc, $userrc, $dorc, $mech, $pw,
++ $tlskey, $notls) =
+ ('', 143, undef, $ENV{USER} || $ENV{LOGNAME}, '/etc/cyradmrc.pl',
+- "$ENV{HOME}/.cyradmrc.pl", 1, undef, undef);
++ "$ENV{HOME}/.cyradmrc.pl", 1, undef, undef, "", undef);
+ GetOptions('user|u=s' => \$auth,
+ 'authz|z=s' => \$authz,
+ 'rc|r!' => \$dorc,
+@@ -448,6 +449,8 @@
+ 'port|p=i' => \$port,
+ 'auth|a=s' => \$mech,
+ 'password|w=s' => \$pw,
++ 'tlskey|t=s' => \$tlskey,
++ 'notls' => \$notls,
+ 'help|h' => sub { cyradm_usage(); exit(0); }
+ );
+ if ($server ne '' && @ARGV) {
+@@ -466,7 +469,8 @@
+ -callback => \&_cb_eof,
+ -rock => \$cyradm});
+ $cyradm->authenticate(-authz => $authz, -user => $auth,
+- -mechanism => $mech, -password => $pw)
++ -mechanism => $mech, -password => $pw,
++ -tlskey => $tlskey, -notls => $notls)
+ or die "cyradm: cannot authenticate to server" . (defined($mech)?" with $mech":"") . " as $auth\n";
+ }
+ my $fstk = [*STDIN, *STDOUT, *STDERR];
+@@ -773,6 +777,34 @@
+ $want = '-service';
+ next;
+ }
++ if (Cyrus::IMAP::imclient_havetls()) {
++ if ($opt ne '' && '-tlskey' =~ /^\Q$opt/ || $opt eq '--tlskey') {
++ $want = '-tlskey';
++ next;
++ }
++ if ($opt ne '' && '-notls' =~ /^\Q$opt/ || $opt eq '--notls') {
++ $want = '-notls';
++ next;
++ }
++ if ($opt =~ /^-/) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ }
++ }
++ if (Cyrus::IMAP::imclient_havetls()) {
++ if ($opt ne '' && '-tlskey' =~ /^\Q$opt/ || $opt eq '--tlskey') {
++ $want = '-tlskey';
++ next;
++ }
++ if ($opt ne '' && '-notls' =~ /^\Q$opt/ || $opt eq '--notls') {
++ $want = '-notls';
++ next;
++ }
++ if ($opt =~ /^-/) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ }
++ }
+ if ($opt =~ /^-/) {
+ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
+ " [-service name] [user]\n";
+@@ -784,8 +816,13 @@
+ }
+ push(@nargv, @argv);
+ if (@nargv > 1) {
+- die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
+- " [-service name] [user]\n";
++ if (Cyrus::IMAP::imclient_havetls()) {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [-tlskey keyfile] [-notls] [user]\n";
++ } else {
++ die "usage: authenticate [-minssf N] [-maxssf N] [-mechanisms STR]\n".
++ " [-service name] [user]\n";
++ }
+ }
+ if (@nargv) {
+ $opts{-user} = shift(@nargv);
+diff -urNad sarge-2.2.13/perl/imap/IMAP.pm /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.pm
+--- sarge-2.2.13/perl/imap/IMAP.pm 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.pm 2007-03-08 16:42:22.307556244 +0100
+@@ -196,16 +196,43 @@
+ sub authenticate {
+ my ($self, $first) = @_;
+ my (%opts, $rc);
++ my ($starttls, $logindisabled) = (0, 0);
+
+ if (defined $first &&
+- $first =~ /^-\w+|Mechanism|Service|Authz|User|Minssf|Maxssf|Password$/) {
++ $first =~ /^-\w+|Mechanism|Service|Authz|User|Minssf|Maxssf|Password|Tlskey|Notls|CAfile|CApath$/) {
+ (undef, %opts) = @_;
+- foreach (qw(mechanism service authz user minssf maxssf password)) {
++ foreach (qw(mechanism service authz user minssf maxssf password tlskey notls)) {
+ $opts{'-' . $_} = $opts{ucfirst($_)} if !defined($opts{'-' . $_});
+ }
+ } else {
+ (undef, $opts{-mechanism}, $opts{-service}, $opts{-authz}, $opts{-user},
+- $opts{-minssf}, $opts{-maxssf}, $opts{-password}) = @_;
++ $opts{-minssf}, $opts{-maxssf}, $opts{-password},
++ $opts{-tlskey}, $opts{-notls}, $opts{-cafile}, $opts{-capath}) = @_;
++ }
++ if (havetls()) {
++ if (!defined($opts{-tlskey})) {
++ $opts{-tlskey} = "";
++ }
++ if (!defined($opts{-cafile})) {
++ $opts{-cafile} = "";
++ }
++ if (!defined($opts{-capath})) {
++ $opts{-capath} = "";
++ }
++ if ($opts{-notls}) {
++ $opts{-tlskey} = undef;
++ }
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $starttls = 1
++ if /^STARTTLS$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($starttls && defined($opts{-tlskey})) {
++ $self->_starttls($opts{-tlskey}, $opts{-tlskey}, $opts{-cafile}, $opts{-capath});
++ }
+ }
+ if (!defined($opts{-mechanism})) {
+ $opts{-mechanism} = '';
+@@ -234,6 +261,34 @@
+ $opts{-authz}, $opts{-user}, $opts{-password},
+ $opts{-minssf}, $opts{-maxssf});
+ }
++ if (!$rc) {
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $logindisabled = 1
++ if /^LOGINDISABLED$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($logindisabled) {
++ warn "Login disabled.\n";
++ return undef;
++ }
++ }
++ if (!$rc) {
++ $self->addcallback({-trigger => 'CAPABILITY',
++ -callback => sub {my %a = @_;
++ map { $logindisabled = 1
++ if /^LOGINDISABLED$/i;
++ }
++ split(/ /, $a{-text})}});
++ $self->send(undef, undef, 'CAPABILITY');
++ $self->addcallback({-trigger => 'CAPABILITY'});
++ if ($logindisabled) {
++ warn "Login disabled.\n";
++ return undef;
++ }
++ }
+ $opts{-mechanism} ||= 'plain';
+ if (!$rc && $opts{-mechanism} =~ /(\b|^)(plain|login)($|\b)/i) {
+ $opts{-user} = getlogin if !defined($opts{-user});
+diff -urNad sarge-2.2.13/perl/imap/IMAP.xs /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.xs
+--- sarge-2.2.13/perl/imap/IMAP.xs 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/IMAP.xs 2007-03-08 16:42:22.308556145 +0100
+@@ -57,6 +57,7 @@
+ #include "xmalloc.h"
+
+ #include "cyrperl.h"
++#include "config.h"
+
+ typedef struct xscyrus *Cyrus_IMAP;
+
+@@ -417,6 +418,82 @@
+ ST(0) = &sv_yes;
+ }
+
++int
++imclient_havetls()
++CODE:
++#ifdef HAVE_SSL
++ RETVAL = 1;
++#else
++ RETVAL = 0;
++#endif /* HAVE_SSL */
++OUTPUT:
++ RETVAL
++
++SV *
++imclient__starttls(client, tls_cert_file, tls_key_file, CAfile, CApath)
++ Cyrus_IMAP client
++ char* tls_cert_file
++ char* tls_key_file
++ char* CAfile
++ char* CApath
++PREINIT:
++ int rc;
++ int tls_layer;
++CODE:
++ ST(0) = sv_newmortal();
++
++ /* If the tls_{cert, key}_file parameters are undef, set to be NULL */
++ if(!SvOK(ST(2))) tls_cert_file = NULL;
++ if(!SvOK(ST(3))) tls_key_file = NULL;
++#ifdef HAVE_SSL
++ rc = imclient_starttls(client->imclient, tls_cert_file, tls_key_file, CAfile, CApath);
++ if (rc)
++ ST(0) = &sv_no;
++ else {
++ ST(0) = &sv_yes;
++ }
++#else
++ ST(0) = &sv_no;
++#endif /* HAVE_SSL */
++
++int
++imclient_havetls()
++CODE:
++#ifdef HAVE_SSL
++ RETVAL = 1;
++#else
++ RETVAL = 0;
++#endif /* HAVE_SSL */
++OUTPUT:
++ RETVAL
++
++SV *
++imclient__starttls(client, tls_cert_file, tls_key_file, CAfile, CApath)
++ Cyrus_IMAP client
++ char* tls_cert_file
++ char* tls_key_file
++ char* CAfile
++ char* CApath
++PREINIT:
++ int rc;
++ int tls_layer;
++CODE:
++ ST(0) = sv_newmortal();
++
++ /* If the tls_{cert, key}_file parameters are undef, set to be NULL */
++ if(!SvOK(ST(2))) tls_cert_file = NULL;
++ if(!SvOK(ST(3))) tls_key_file = NULL;
++#ifdef HAVE_SSL
++ rc = imclient_starttls(client->imclient, tls_cert_file, tls_key_file, CAfile, CApath);
++ if (rc)
++ ST(0) = &sv_no;
++ else {
++ ST(0) = &sv_yes;
++ }
++#else
++ ST(0) = &sv_no;
++#endif /* HAVE_SSL */
++
+ void
+ imclient_addcallback(client, ...)
+ Cyrus_IMAP client
+diff -urNad sarge-2.2.13/perl/imap/Makefile.PL /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/Makefile.PL
+--- sarge-2.2.13/perl/imap/Makefile.PL 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/Makefile.PL 2007-03-08 16:42:22.308556145 +0100
+@@ -1,5 +1,4 @@
+ #
+-# Copyright (c) 2000 Carnegie Mellon University. All rights reserved.
+ #
+ # Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions
+@@ -66,7 +65,7 @@
+ 'OBJECT' => 'IMAP.o',
+ 'MYEXTLIB' => '../../lib/libcyrus.a ../../lib/libcyrus_min.a',
+ 'LIBS' => ["$BDB_LIB $SASL_LIB $OPENSSL_LIB $LIB_RT -lssl -lcrypto"],
+- 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
+- 'INC' => "-I../../lib $SASL_INC $OPENSSL_INC",
++ 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
++ 'INC' => "-I../../lib -I../.. $SASL_INC $OPENSSL_INC",
+ 'EXE_FILES' => [cyradm],
+ );
+diff -urNad sarge-2.2.13/perl/imap/cyradm.sh /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/cyradm.sh
+--- sarge-2.2.13/perl/imap/cyradm.sh 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/imap/cyradm.sh 2007-03-08 16:42:22.309556046 +0100
+@@ -54,7 +54,8 @@
+ =head1 SYNOPSIS
+
+ $ cyradm [--user user] [--[no]rc] [--systemrc file] [--userrc file] \
+- > [--port n] [--auth mechanism] [--server] server
++ > [--port n] [--auth mechanism] [--tlskey keyfile] [--notls] \
++ > [--server] server
+
+ but possibly
+
+diff -urNad sarge-2.2.13/perl/sieve/lib/isieve.c /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.c
+--- sarge-2.2.13/perl/sieve/lib/isieve.c 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.c 2007-03-08 16:42:22.311555847 +0100
+@@ -45,6 +45,10 @@
+ #include <config.h>
+ #endif
+
++#include <assert.h>
++
++#include <assert.h>
++
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+@@ -59,6 +63,24 @@
+ #include <sasl/sasl.h>
+ #include <sasl/saslutil.h>
+
++#ifdef HAVE_SSL
++#include <openssl/lhash.h>
++#include <openssl/bn.h>
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/x509.h>
++#include <openssl/ssl.h>
++#endif /* HAVE_SSL */
++
++#ifdef HAVE_SSL
++#include <openssl/lhash.h>
++#include <openssl/bn.h>
++#include <openssl/err.h>
++#include <openssl/pem.h>
++#include <openssl/x509.h>
++#include <openssl/ssl.h>
++#endif /* HAVE_SSL */
++
+ #include "isieve.h"
+ #include "lex.h"
+ #include "request.h"
+@@ -81,13 +103,27 @@
+ sasl_callback_t *refer_callbacks;
+
+ int version;
++ int starttls;
++ char *tls_keyfile;
+
+ struct protstream *pin;
+ struct protstream *pout;
++
++#ifdef HAVE_SSL
++ SSL_CTX *tls_ctx;
++ SSL *tls_conn;
++#endif /* HAVE_SSL */
+ };
+
+ void fillin_interactions(sasl_interact_t *tlist);
+
++#ifdef HAVE_SSL
++static int isieve_starttls(isieve_t *obj, int verifydepth,
++ char *var_tls_cert_file, char *var_tls_key_file,
++ int *layer);
++#endif /* HAVE_SSL */
++
++
+ /* we need this separate from the free() call so that we can reuse
+ * the same memory for referrals */
+ static void sieve_dispose(isieve_t *obj)
+@@ -277,7 +313,7 @@
+ } else if (strcasecmp(attr,"IMPLEMENTATION")==0) {
+
+ } else if (strcasecmp(attr,"STARTTLS")==0) {
+- /* TODO */
++ obj->starttls = 1;
+ } else if (val && strncmp(val,"SASL=",5)==0) {
+ obj->version = OLD_VERSION;
+ cap = (char *) xmalloc(strlen(val));
+@@ -351,6 +387,64 @@
+ return STAT_CONT;
+ }
+
++int auth_starttls(isieve_t *obj, char *tls_keyfile,
++ char **mechlist, char **errstr)
++{
++ unsigned ext_ssf = 0;
++ int ret;
++ char *refer_to;
++
++ if (!obj->tls_keyfile) obj->tls_keyfile = tls_keyfile;
++
++ if (!obj->starttls || !obj->tls_keyfile) return 0;
++
++#ifdef HAVE_SSL
++ ret = starttls(obj->version, obj->pout, obj->pin, &refer_to, errstr);
++ /* xxx handle referrals */
++ if (ret != 0) return -1;
++
++ ret = isieve_starttls(obj, 0, tls_keyfile, tls_keyfile, &ext_ssf);
++ if (ret != 0) return -1;
++
++ prot_printf(obj->pout, "CAPABILITY\r\n");
++ prot_flush(obj->pout);
++
++ if (*mechlist) free(*mechlist);
++ *mechlist = read_capability(obj);
++#endif /* HAVE_SSL */
++
++ return 0;
++}
++
++int auth_starttls(isieve_t *obj, char *tls_keyfile,
++ char **mechlist, char **errstr)
++{
++ unsigned ext_ssf = 0;
++ int ret;
++ char *refer_to;
++
++ if (!obj->tls_keyfile) obj->tls_keyfile = tls_keyfile;
++
++ if (!obj->starttls || !obj->tls_keyfile) return 0;
++
++#ifdef HAVE_SSL
++ ret = starttls(obj->version, obj->pout, obj->pin, &refer_to, errstr);
++ /* xxx handle referrals */
++ if (ret != 0) return -1;
++
++ ret = isieve_starttls(obj, 0, tls_keyfile, tls_keyfile, &ext_ssf);
++ if (ret != 0) return -1;
++
++ prot_printf(obj->pout, "CAPABILITY\r\n");
++ prot_flush(obj->pout);
++
++ if (*mechlist) free(*mechlist);
++ *mechlist = read_capability(obj);
++#endif /* HAVE_SSL */
++
++ return 0;
++}
++
+
+ int auth_sasl(char *mechlist, isieve_t *obj, const char **mechusing,
+ char **errstr)
+@@ -590,6 +684,14 @@
+ /* Authenticate */
+ mechlist = read_capability(obj_new);
+
++ /* Perform STARTTLS */
++ ret = auth_starttls(obj, obj->tls_keyfile, &mechlist, &errstr);
++ if (ret) return STAT_NO;
++
++ /* Perform STARTTLS */
++ ret = auth_starttls(obj, obj->tls_keyfile, &mechlist, &errstr);
++ if (ret) return STAT_NO;
++
+ do {
+ mtried = NULL;
+ ret = auth_sasl(mechlist, obj_new, &mtried, &errstr);
+@@ -751,3 +853,342 @@
+
+ return ret;
+ }
++
++/*************** All these functions help do the starttls; these are copied from imclient.c ********/
++#ifdef HAVE_SSL
++
++static int verify_depth;
++static int verify_error = X509_V_OK;
++
++#define CCERT_BUFSIZ 256
++static char peer_CN[CCERT_BUFSIZ];
++static char issuer_CN[CCERT_BUFSIZ];
++
++/*
++ * Set up the cert things on the server side. We do need both the
++ * private key (in key_file) and the cert (in cert_file).
++ * Both files may be identical.
++ *
++ * This function is taken from OpenSSL apps/s_cb.c
++ */
++
++static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file)
++{
++ if (cert_file != NULL) {
++ if (SSL_CTX_use_certificate_file(ctx, cert_file,
++ SSL_FILETYPE_PEM) <= 0) {
++ printf("[ unable to get certificate from '%s' ]\n", cert_file);
++ return (0);
++ }
++ if (key_file == NULL)
++ key_file = cert_file;
++ if (SSL_CTX_use_PrivateKey_file(ctx, key_file,
++ SSL_FILETYPE_PEM) <= 0) {
++ printf("[ unable to get private key from '%s' ]\n", key_file);
++ return (0);
++ }
++ /* Now we know that a key and cert have been set against
++ * the SSL context */
++ if (!SSL_CTX_check_private_key(ctx)) {
++ printf("[ Private key does not match the certificate public key ]\n");
++ return (0);
++ }
++ }
++ return (1);
++}
++
++/* taken from OpenSSL apps/s_cb.c */
++
++static int verify_callback(int ok, X509_STORE_CTX * ctx)
++{
++ char buf[256];
++ X509 *err_cert;
++ int err;
++ int depth;
++
++ err_cert = X509_STORE_CTX_get_current_cert(ctx);
++ err = X509_STORE_CTX_get_error(ctx);
++ depth = X509_STORE_CTX_get_error_depth(ctx);
++
++ X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
++
++ /* if (verbose==1)
++ printf("Peer cert verify depth=%d %s\n", depth, buf);*/
++
++ if (!ok) {
++ printf("verify error:num=%d:%s\n", err,
++ X509_verify_cert_error_string(err));
++ if (verify_depth >= depth) {
++ ok = 1;
++ verify_error = X509_V_OK;
++ } else {
++ ok = 0;
++ verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
++ }
++ }
++ switch (ctx->error) {
++ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
++ X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
++ printf("issuer= %s\n", buf);
++ break;
++ case X509_V_ERR_CERT_NOT_YET_VALID:
++ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
++ printf("cert not yet valid\n");
++ break;
++ case X509_V_ERR_CERT_HAS_EXPIRED:
++ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
++ printf("cert has expired\n");
++ break;
++ }
++
++ /* if (verbose==1)
++ printf("verify return:%d\n", ok);*/
++
++ return (ok);
++}
++
++
++/* taken from OpenSSL apps/s_cb.c */
++static RSA *tmp_rsa_cb(SSL *s __attribute__((unused)),
++ int export __attribute__((unused)),
++ int keylength)
++{
++ static RSA *rsa_tmp = NULL;
++
++ if (rsa_tmp == NULL) {
++ rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL);
++ }
++ return (rsa_tmp);
++}
++
++/*
++ * Seed the random number generator.
++ */
++static int tls_rand_init(void)
++{
++#ifdef EGD_SOCKET
++ return (RAND_egd(EGD_SOCKET));
++#else
++ /* otherwise let OpenSSL do it internally */
++ return 0;
++#endif
++}
++
++static char *var_tls_CAfile="";
++static char *var_tls_CApath="";
++ /*
++ * This is the setup routine for the SSL client.
++ *
++ * The skeleton of this function is taken from OpenSSL apps/s_client.c.
++ */
++
++static int tls_init_clientengine(isieve_t *obj,
++ int verifydepth, char *var_tls_cert_file, char *var_tls_key_file)
++{
++ int off = 0;
++ int verify_flags = SSL_VERIFY_NONE;
++ char *CApath;
++ char *CAfile;
++ char *c_cert_file;
++ char *c_key_file;
++
++ assert(obj);
++
++ SSL_load_error_strings();
++ SSLeay_add_ssl_algorithms();
++ if (tls_rand_init() == -1) {
++ printf("[ TLS engine: cannot seed PRNG ]\n");
++ return -1;
++ }
++
++ obj->tls_ctx = SSL_CTX_new(TLSv1_client_method());
++ if (obj->tls_ctx == NULL) {
++ return -1;
++ };
++
++ off |= SSL_OP_ALL; /* Work around all known bugs */
++ SSL_CTX_set_options(obj->tls_ctx, off);
++
++ /* debugging SSL_CTX_set_info_callback(obj->tls_ctx, apps_ssl_info_callback); */
++
++ if (strlen(var_tls_CAfile) == 0)
++ CAfile = NULL;
++ else
++ CAfile = var_tls_CAfile;
++ if (strlen(var_tls_CApath) == 0)
++ CApath = NULL;
++ else
++ CApath = var_tls_CApath;
++
++ if (CAfile || CApath)
++ if ((!SSL_CTX_load_verify_locations(obj->tls_ctx, CAfile, CApath)) ||
++ (!SSL_CTX_set_default_verify_paths(obj->tls_ctx))) {
++ printf("[ TLS engine: cannot load CA data ]\n");
++ return -1;
++ }
++ if (strlen(var_tls_cert_file) == 0)
++ c_cert_file = NULL;
++ else
++ c_cert_file = var_tls_cert_file;
++ if (strlen(var_tls_key_file) == 0)
++ c_key_file = NULL;
++ else
++ c_key_file = var_tls_key_file;
++
++ if (c_cert_file || c_key_file)
++ if (!set_cert_stuff(obj->tls_ctx, c_cert_file, c_key_file)) {
++ printf("[ TLS engine: cannot load cert/key data ]\n");
++ return -1;
++ }
++ SSL_CTX_set_tmp_rsa_callback(obj->tls_ctx, tmp_rsa_cb);
++
++ verify_depth = verifydepth;
++ SSL_CTX_set_verify(obj->tls_ctx, verify_flags, verify_callback);
++
++ return 0;
++}
++
++
++static int tls_start_clienttls(isieve_t *obj,
++ unsigned *layer, char **authid, int fd)
++{
++ int sts;
++ SSL_SESSION *session;
++ SSL_CIPHER *cipher;
++ X509 *peer;
++ const char *tls_protocol = NULL;
++ const char *tls_cipher_name = NULL;
++ int tls_cipher_usebits = 0;
++ int tls_cipher_algbits = 0;
++ char *tls_peer_CN = "";
++ char *tls_issuer_CN = NULL;
++
++ if (obj->tls_conn == NULL) {
++ obj->tls_conn = (SSL *) SSL_new(obj->tls_ctx);
++ }
++ if (obj->tls_conn == NULL) {
++ printf("Could not allocate 'con' with SSL_new()\n");
++ return -1;
++ }
++ SSL_clear(obj->tls_conn);
++
++ if (!SSL_set_fd(obj->tls_conn, fd)) {
++ printf("SSL_set_fd failed\n");
++ return -1;
++ }
++
++ /*SSL_set_read_ahead(obj->tls_conn, 1);*/
++
++ /*
++ * This is the actual handshake routine. It will do all the negotiations
++ * and will check the client cert etc.
++ */
++ SSL_set_connect_state(obj->tls_conn);
++
++
++ /*
++ * We do have an SSL_set_fd() and now suddenly a BIO_ routine is called?
++ * Well there is a BIO below the SSL routines that is automatically
++ * created for us, so we can use it for debugging purposes.
++ */
++ /* if (verbose==1) */
++ /* BIO_set_callback(SSL_get_rbio(obj->tls_conn), bio_dump_cb);*/
++
++ /* Dump the negotiation for loglevels 3 and 4 */
++
++ if ((sts = SSL_connect(obj->tls_conn)) <= 0) {
++ printf("[ SSL_connect error %d ]\n", sts); /* xxx get string error? */
++ session = SSL_get_session(obj->tls_conn);
++ if (session) {
++ SSL_CTX_remove_session(obj->tls_ctx, session);
++ printf("[ SSL session removed ]\n");
++ }
++ if (obj->tls_conn!=NULL)
++ SSL_free(obj->tls_conn);
++ obj->tls_conn = NULL;
++ return -1;
++ }
++
++ /*
++ * Lets see, whether a peer certificate is availabe and what is
++ * the actual information. We want to save it for later use.
++ */
++ peer = SSL_get_peer_certificate(obj->tls_conn);
++ if (peer != NULL) {
++ X509_NAME_get_text_by_NID(X509_get_subject_name(peer),
++ NID_commonName, peer_CN, CCERT_BUFSIZ);
++ tls_peer_CN = peer_CN;
++ X509_NAME_get_text_by_NID(X509_get_issuer_name(peer),
++ NID_commonName, issuer_CN, CCERT_BUFSIZ);
++ /* if (verbose==1)
++ printf("subject_CN=%s, issuer_CN=%s\n", peer_CN, issuer_CN);*/
++ tls_issuer_CN = issuer_CN;
++
++ }
++ tls_protocol = SSL_get_version(obj->tls_conn);
++ cipher = SSL_get_current_cipher(obj->tls_conn);
++ tls_cipher_name = SSL_CIPHER_get_name(cipher);
++ tls_cipher_usebits = SSL_CIPHER_get_bits(cipher,
++ &tls_cipher_algbits);
++
++ if (layer!=NULL)
++ *layer = tls_cipher_usebits;
++
++ if (authid!=NULL)
++ *authid = tls_peer_CN;
++
++ /* printf("TLS connection established: %s with cipher %s (%d/%d bits)\n",
++ tls_protocol, tls_cipher_name,
++ tls_cipher_usebits, tls_cipher_algbits);*/
++ return 0;
++}
++
++static int isieve_starttls(isieve_t *obj,
++ int verifydepth __attribute__((unused)),
++ char *var_tls_cert_file,
++ char *var_tls_key_file,
++ int *layer __attribute__((unused)))
++{
++ int result;
++ unsigned ssf;
++ char *auth_id;
++
++ result=tls_init_clientengine(obj, 10, var_tls_cert_file, var_tls_key_file);
++ if (result!=0)
++ {
++ printf("[ TLS engine failed ]\n");
++ return 1;
++ } else {
++ result=tls_start_clienttls(obj, &ssf, &auth_id, obj->sock);
++
++ if (result!=0) {
++ printf("[ TLS negotiation did not succeed ]\n");
++ return 1;
++ }
++ }
++
++ /* turn non-blocking i/o back on */
++
++
++ /* TLS negotiation succeeded */
++
++ auth_id=""; /* xxx this really should be peer_CN or
++ issuer_CN but I can't figure out which is
++ which at the moment */
++
++ /* tell SASL about the negotiated layer */
++ result=sasl_setprop(obj->conn,
++ SASL_SSF_EXTERNAL,
++ &ssf);
++ if (result!=SASL_OK) return 1;
++ result=sasl_setprop(obj->conn,
++ SASL_AUTH_EXTERNAL,
++ auth_id);
++ if (result!=SASL_OK) return 1;
++
++ prot_settls (obj->pin, obj->tls_conn);
++ prot_settls (obj->pout, obj->tls_conn);
++
++ return 0;
++}
++#endif /* HAVE_SSL */
+diff -urNad sarge-2.2.13/perl/sieve/lib/isieve.h /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.h
+--- sarge-2.2.13/perl/sieve/lib/isieve.h 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/isieve.h 2007-03-08 16:42:22.312555748 +0100
+@@ -67,6 +67,7 @@
+ STAT_OK = 2
+ } imt_stat;
+
++int auth_starttls(isieve_t *obj, char *tls_keyfile, char **mechlist, char **errstr);
+ int auth_sasl(char *mechlist, isieve_t *obj, const char **mechusing, char **errstr);
+
+ int isieve_logout(isieve_t **obj);
+diff -urNad sarge-2.2.13/perl/sieve/lib/request.c /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.c
+--- sarge-2.2.13/perl/sieve/lib/request.c 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.c 2007-03-08 16:42:22.313555649 +0100
+@@ -168,22 +168,24 @@
+ /* SASL response */
+ res = yylex(&state, pin);
+ if(res == ' ') {
+- if (yylex(&state, pin) != '(')
+- parseerror("expected LPAREN");
+-
+- if (yylex(&state, pin)==TOKEN_SASL) {
+- if (yylex(&state, pin)!=' ')
+- parseerror("expected space");
+- if (yylex(&state, pin)!=STRING)
+- parseerror("expected string");
++ res = yylex(&state, pin);
++ if (res == '(') {
++ if (yylex(&state, pin)==TOKEN_SASL) {
++ if (yylex(&state, pin)!=' ')
++ parseerror("expected space");
++ if (yylex(&state, pin)!=STRING)
++ parseerror("expected string");
+
+- *refer_to = xstrdup(string_DATAPTR(state.str));
++ *refer_to = xstrdup(string_DATAPTR(state.str));
+
+- if (yylex(&state, pin)!=')')
+- parseerror("expected RPAREN");
+- } else {
+- parseerror("unexpected response code with OK response");
++ if (yylex(&state, pin) != ')')
++ parseerror("expected RPAREN");
++ res = yylex(&state, pin);
++ if (res == ' ') res = yylex(&state, pin);
++ }
+ }
++ if (res != STRING)
++ parseerror("unexpected response code with OK response");
+ } else if (version != OLD_VERSION && res == EOL) {
+ return r;
+ }
+@@ -637,3 +639,59 @@
+ return 0;
+
+ }
++
++
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstrp)
++{
++ lexstate_t state;
++ int res;
++ int ret;
++ mystring_t *errstr;
++
++ prot_printf(pout, "STARTTLS\r\n");
++ prot_flush(pout);
++
++ res = yylex(&state, pin);
++
++ ret = handle_response(res, version, pin, refer_to, &errstr);
++
++ /* if command failed */
++ if(ret == -2 && *refer_to) {
++ return -2;
++ } else if (ret != 0) {
++ *errstrp = malloc(128);
++ snprintf(*errstrp, 127,
++ "Starttls: %s",string_DATAPTR(errstr));
++ return -1;
++ }
++ return 0;
++}
++
++
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstrp)
++{
++ lexstate_t state;
++ int res;
++ int ret;
++ mystring_t *errstr;
++
++ prot_printf(pout, "STARTTLS\r\n");
++ prot_flush(pout);
++
++ res = yylex(&state, pin);
++
++ ret = handle_response(res, version, pin, refer_to, &errstr);
++
++ /* if command failed */
++ if(ret == -2 && *refer_to) {
++ return -2;
++ } else if (ret != 0) {
++ *errstrp = malloc(128);
++ snprintf(*errstrp, 127,
++ "Starttls: %s",string_DATAPTR(errstr));
++ return -1;
++ }
++ return 0;
++}
+diff -urNad sarge-2.2.13/perl/sieve/lib/request.h /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.h
+--- sarge-2.2.13/perl/sieve/lib/request.h 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/lib/request.h 2007-03-08 16:42:22.313555649 +0100
+@@ -91,5 +91,7 @@
+
+ void parseerror(char *str);
+
++int starttls(int version, struct protstream *pout, struct protstream *pin,
++ char **refer_to, char **errstr);
+
+ #endif
+diff -urNad sarge-2.2.13/perl/sieve/managesieve/Makefile.PL /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/Makefile.PL
+--- sarge-2.2.13/perl/sieve/managesieve/Makefile.PL 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/Makefile.PL 2007-03-08 16:42:22.313555649 +0100
+@@ -46,6 +46,7 @@
+ my $SASL_LIB = $ENV{SASL_LIB} || "-lsasl2";
+ my $OPENSSL_INC = $ENV{OPENSSL_INC};
+ my $OPENSSL_LIB = $ENV{OPENSSL_LIB};
++my $HAVE_SSL = $OPENSSL_LIB ? "-DHAVE_SSL" : '';
+ my $BDB_INC = $ENV{BDB_INC};
+ my $BDB_LIB = $ENV{BDB_LIB};
+
+@@ -61,7 +62,7 @@
+ 'VERSION_FROM' => 'managesieve.pm', # finds $VERSION
+ 'MYEXTLIB' => '../lib/isieve.o ../lib/lex.o ../lib/mystring.o ../lib/request.o ../../../lib/libcyrus.a ../../../lib/libcyrus_min.a',
+ 'LIBS' => ["$BDB_LIB $SASL_LIB $OPENSSL_LIB $LIB_RT -lssl -lcrypto"],
+- 'DEFINE' => '-DPERL_POLLUTE', # e.g., '-DHAVE_SOMETHING'
++ 'DEFINE' => "-DPERL_POLLUTE $HAVE_SSL", # e.g., '-DHAVE_SOMETHING'
+ 'INC' => "-I../lib/ -I../../../lib/ $SASL_INC $OPENSSL_INC",
+ 'CC' => $ENV{CC},
+ 'LD' => $ENV{CC}
+diff -urNad sarge-2.2.13/perl/sieve/managesieve/managesieve.xs /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/managesieve.xs
+--- sarge-2.2.13/perl/sieve/managesieve/managesieve.xs 2007-03-08 16:31:22.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/managesieve/managesieve.xs 2007-03-08 16:42:22.314555550 +0100
+@@ -211,12 +211,13 @@
+
+
+ Sieveobj
+-sieve_get_handle(servername, username_cb, authname_cb, password_cb, realm_cb)
++sieve_get_handle(servername, username_cb, authname_cb, password_cb, realm_cb, tls_keyfile)
+ char *servername
+ SV *username_cb
+ SV *authname_cb
+ SV *password_cb
+ SV *realm_cb
++ char *tls_keyfile
+
+ PREINIT:
+ Sieveobj ret = NULL;
+@@ -249,6 +250,10 @@
+ callbacks[3].context = password_cb;
+ callbacks[4].id = SASL_CB_LIST_END;
+
++ if (!SvOK(ST(5))) tls_keyfile = NULL;
++
++ if (!SvOK(ST(5))) tls_keyfile = NULL;
++
+ /* see if we have server:port (or IPv6, etc)*/
+ p = servername;
+ if (*servername == '[') {
+@@ -299,6 +304,16 @@
+ XSRETURN_UNDEF;
+ }
+
++ if (auth_starttls(obj, tls_keyfile, &mlist, &ret->errstr) != 0) {
++ globalerr = "starttls failed";
++ XSRETURN_UNDEF;
++ }
++
++ if (auth_starttls(obj, tls_keyfile, &mlist, &ret->errstr) != 0) {
++ globalerr = "starttls failed";
++ XSRETURN_UNDEF;
++ }
++
+ /* loop through all the mechanisms */
+ do {
+ mtried = NULL;
+diff -urNad sarge-2.2.13/perl/sieve/scripts/installsieve.pl /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/installsieve.pl
+--- sarge-2.2.13/perl/sieve/scripts/installsieve.pl 2007-03-08 16:40:29.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/installsieve.pl 2007-03-08 16:42:22.315555451 +0100
+@@ -44,6 +44,7 @@
+ use Getopt::Long;
+
+ $username = "";
++$tls_keyfile = "";
+
+ print "NOTE: This program is deprecated. Please use sieveshell\n";
+ print "\n";
+@@ -55,6 +56,8 @@
+ "a|activates:s" => \$activates,
+ "d|deletes:s" => \$deletes,
+ # "m|mechanism:s" => \$mech,
++ "t|tlskey:s" => \$tls_keyfile,
++ "n|notls" => \$notls,
+ "g|gets:s" => \$gets,
+ "u|username:s" => \$username,
+ # "w|password:s" => \$pass
+@@ -66,6 +69,14 @@
+
+ $acapserver = $ARGV[0];
+
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
+ sub list_cb {
+
+ my($name, $isactive) = @_ ;
+@@ -113,11 +124,13 @@
+ print " -g <name> Get script <name> and save to disk\n";
+ print " -u <user> Userid/Authname to use\n";
+ # print " -w <passwd> Specify password (Should only be used for automated scripts)\n";
++ print " -t <keyfile> TLS keyfile to use\n";
++ print " -n Don't use TLS\n";
+ print "\n";
+ }
+
+ #main code
+-my $obj = sieve_get_handle($acapserver,"prompt","prompt","prompt","prompt");
++my $obj = sieve_get_handle($acapserver,"prompt","prompt","prompt","prompt", $tls_keyfile);
+
+ if (!defined $obj) {
+ die "Unable to connect to server";
+diff -urNad sarge-2.2.13/perl/sieve/scripts/sieveshell.pl /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/sieveshell.pl
+--- sarge-2.2.13/perl/sieve/scripts/sieveshell.pl 2007-03-08 16:40:31.000000000 +0100
++++ /tmp/dpep.9n8yig/sarge-2.2.13/perl/sieve/scripts/sieveshell.pl 2007-03-08 16:42:22.316555352 +0100
+@@ -61,6 +61,8 @@
+ my $authname = $ENV{USER};
+ my $realm = "";
+ my $password;
++my $tls_keyfile = "";
++my $notls = 0;
+ my $ex = "";
+ my $exfile = "";
+ my $help = 0;
+@@ -71,6 +73,8 @@
+ "u|username:s" => \$username,
+ "r|realm:s" => \$realm,
+ "p|password:s" => \$password,
++ "t|tlskey:s" => \$tls_keyfile,
++ "n|notls" => \$notls,
+ "e|exec:s" => \$ex,
+ "f|execfile:s" => \$exfile,
+ "help|?" => \$help,
+@@ -84,6 +88,14 @@
+
+ my $acapserver = $ARGV[0];
+
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
++if ($notls) {
++ $tls_keyfile = undef;
++}
++
+ my $filehandle;
+ my $interactive;
+
+@@ -156,7 +168,7 @@
+
+ sub show_help {
+ print "Usage:\n";
+- print " sieveshell [-u username] [-a authname] [-r realm] <server>\n";
++ print " sieveshell [-u username] [-a authname] [-r realm] [-t keyfile] [-n] <server>\n";
+ print "\n";
+ print "help - this screen\n";
+ print "list - list scripts on server\n";
+@@ -173,7 +185,7 @@
+ print "connecting to $acapserver\n";
+
+ my $obj = sieve_get_handle($acapserver,
+- "prompt", "prompt", "prompt", "prompt");
++ "prompt", "prompt", "prompt", "prompt", $tls_keyfile);
+
+ if (!defined $obj) {
+ die "unable to connect to server";
+@@ -318,6 +330,7 @@
+
+ sieveshell [B<--user>=I<user>] [B<--authname>=I<authname>]
+ [B<--realm>=I<realm>] [B<--password>=I<password>]
++[B<--tlskey>=I<keyfile>] [B<--notls>]
+ [B<--exec>=I<script>] [B<--execfile>=I<file>] I<server>[B<:>I<port>]
+
+ sieveshell B<--help>
+@@ -362,6 +375,22 @@
+
+ The realm to attempt authentication in.
+
++=item B<-t> I<keyfile>, B<--tlskey>=I<keyfile>
++
++I<keyfile> contains the TLS public and private keys to use.
++
++=item B<-n>, B<--notls>
++
++Disable TLS.
++
++=item B<-t> I<keyfile>, B<--tlskey>=I<keyfile>
++
++I<keyfile> contains the TLS public and private keys to use.
++
++=item B<-n>, B<--notls>
++
++Disable TLS.
++
+ =item B<-p> I<password>, B<--password>=I<password>
+
+ The password to use when authenticating to server. Note that this
Propchange: branches/sarge-2.2.13-cyradm-tls/debian/patches/66-cyradm-tls-enabled.dpatch
------------------------------------------------------------------------------
svn:executable = *
More information about the Pkg-Cyrus-imapd-Debian-devel
mailing list