[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