Subject: How do I send custom IMAP commands with c-client ?

From: "Bennett, Patrick" <[email-masked]>
Date: Thu, 27 Jan 2005 18:36:39 -0500

I just downloaded c-client 2004c1 and am in the early stages of deciding
whether or not I'll be able to use the library.

The library we currently use has worked fairly well, but it is no longer
maintained and is fairly out-of-date (it doesn't support TLS for one) so
I'm investigating new options.

One thing that I need to support however are certain server extensions
that some of our customers rely on.  One extension in particular is the
SunOne (formerly iPlanet) Messaging Server's "PROXYAUTH" command.

It works by performing a normal login with a 'message store admin' user,
then the "PROXYAUTH userid" command can be issued to effectively switch
to the specified user.  The benefit over the existing authuser mechanism
is that the login for the administrative user doesn't have to occur in
the clear (assuming SSL isn't used).   Anyway, discussing the merits of
their extension isn't really the issue.  The reality is as a company
required to integrate with a variety of IMAP servers, we pretty much
have to support this.

So, how do I do this in c-client?  I see no mail_xxx functions or
(exposed) imap_xxx functions for sending arbitrary IMAP commands.

Thanks,

Patrick Bennett

---

From: Mark Crispin <[email-masked]>
Date: Thu, 27 Jan 2005 16:47:32 -0800 (Pacific Standard Time)

Other than modifying the c-client code, there are no specific supported 
interfaces in c-client for sending custom commands.  The reason for this 
is that, among other things, custom commands generally require handling of 
new responses, which in turn forces a modification to the c-client code in 
the response processor.

With that said, it is generally fairly easy to add support for a custom 
command in c-client.  The file that you modify is imap4r1.c.  To send a 
command, you set up a vector of IMAPARGs which represent the arguments to 
your command, then call imap_send() to send it.  imap_send() returns an 
IMAPPARSEDREPLY which you can either handle yourself or pass to imap_OK() 
for general handling.

To field a new untagged response, you need to add a clause to the if-else 
change in imap_parse_unsolicited() of the form:
   else if (!strcmp (reply->key,"MYNEWRESPONSE") .....

As a model, look at how the GETQUOTA command is implemented.  That is, 
look at routine imap_getquota() to see how to send a command, and the 
processor for the QUOTA response (search for "this response has a bizarre 
syntax") to see how to field a response.  You should be able to reuse 
existing parsing routines instead of having to write your own

One final comment.  The whole idea of PROXYAUTH has been obsolete for a 
decade, having been replaced with SASL authentication/authorization ID. 
Rather than implement a bad idea from the past, perhaps you should 
implement the modern, standard way of doing things.  What's more, c-client 
already supports it without you having to do anything.

> The reality is as a company

PROXYAUTH is not part of an IMAP server.

-- Mark --

http://staff.washington.edu/mrc
Science does not emerge from voting, party politics, or public debate.
Si vis pacem, para bellum.

---

From: Patrick Bennett <[email-masked]>
Date: Thu, 27 Jan 2005 22:57:26 -0500

Mark Crispin wrote:

> ...As a model, look at how the GETQUOTA command is implemented.  That 
> is, look at routine imap_getquota() to see how to send a command, and 
> the processor for the QUOTA response (search for "this response has a 
> bizarre syntax") to see how to field a response.  You should be able 
> to reuse existing parsing routines instead of having to write your own

Great, thanks Mark.

>
> One final comment.  The whole idea of PROXYAUTH has been obsolete for 
> a decade, having been replaced with SASL authentication/authorization 
> ID. Rather than implement a bad idea from the past, perhaps you should 
> implement the modern, standard way of doing things.  What's more, 
> c-client already supports it without you having to do anything.

How do I generically support this feature with any given server a 
customer might be using?  Some common servers used are Exchange [for 
some users - although in many cases they would just use our direct 
'Exchange Connector'], CommuniGate Pro, SunOne, MiraPoint, and 
GroupWise.  [Don't get me started on how much of a piece of junk 
GroupWise's IMAP implementation is, but I'm sure you already know that.]

If I could start using SASL 'authentication' support for administrative 
logins that are then authorized as user X (without us having to know 
user X's password) and it worked against a variety of IMAP 
implementations, that would be absolutely *fantastic*.
However, I have to say it's not particularly clear how to do it, since 
my two tests to use it (using mtest) against Exchange and Communigate 
Pro failed.  There's also almost zero documentation about it.  The only 
mention I saw was in RELNOTES and it said to use an * in the userid to 
seperate the identity "if the authentication method doesn't support the 
concept" (call me uninformed, but how would I know this?).  Elsewhere, 
in naming.txt - the /authuser flag is mentioned.  Which is it?  xxx*yyy, 
or /authuser=xxx ?  Either one?

>> The reality is as a company required to integrate with a variety of 
>> IMAP servers, we pretty much have to support this.
>

I'm aware of that, but it's part of an IMAP server extension which we 
added support for years ago and (presumably) need to continue to 
support.  Admittedly, I haven't kept up-to-date with the various 
mail/imap RFC's as I implemented basic IMAP/SMTP/LDAP support for one of 
our mail connector pieces many years ago and it's basically been one of 
those things that has 'just worked' for quite some time.  The features 
our servers need e-mail wise have been pretty straight-forward, so 
that's worked pretty well for a while.  Recently though, some of our 
customers are needing to have their former 'internal-only' unified 
messaging servers be exposed to a larger 'outside' group, so SSL support 
in particular has quickly gone from 'nice-to-have' to a requirement. 
This is where c-client has come in.  SSL support is basically a freebie.  :)

Thanks for your help...
Patrick Bennett

---

From: Mark Crispin <[email-masked]>
Date: Thu, 27 Jan 2005 22:25:46 -0800

On Thu, 27 Jan 2005, Patrick Bennett wrote:
> How do I generically support this feature with any given server a customer 
> might be using?

When you open the mailbox, use the /authuser= option, e.g.
 	{imap.example.com/user=fred/authuser=joe}inbox
where "fred" is the account to be logged into and "joe" is the 
administrator account.

This is documented in naming.txt.

> However, I have to say it's not particularly clear how to do it, since my two 
> tests to use it (using mtest) against Exchange and Communigate Pro failed.

Did you use /authuser=, or did you try to use the "*" hack?

> There's also almost zero documentation about it.  The only mention I saw was 
> in RELNOTES and it said to use an * in the userid to seperate the identity

Don't try to use the "*" hack.  It's only supported by the UW IMAP 
server, and only for ancient clients that can't do SASL.

-- Mark --

---

From: Patrick Bennett <[email-masked]>
Date: Fri, 28 Jan 2005 09:06:44 -0500

Mark Crispin wrote:

>> customer might be using?

Yes, I tried exactly this.  

> ...Did you use /authuser=, or did you try to use the "*" hack? Don't 
> try to use the "*" hack.  It's only supported by the UW IMAP server, 
> and only for ancient clients that can't do SASL.

I tried both actually.  When using /authuser with Exchange I get the 
error 'Can't do /authuser with this server.'  I would assume this is 
simply because Exchange 2003 only supports AUTH=NTLM *grumble* and in 
fact, when connected via SSL, it doesn't advertise any AUTH method at 
all!? (which seems odd to me)

I then set up a local test CommuniGate Pro server to try it.  Using 
mtest (with debug protocol on - and the sensitive flags in imap41.c 
disabled) I get this:
---------
Mailbox ('?' for help): 
{localhost/user=postmaster/authuser=patrickb/novalidate-cert}inbox
[Trying IP address [127.0.0.1]]
* OK CommuniGate Pro IMAP Server 4.2.8 at test1 ready
[CommuniGate Pro IMAP Server 4.2.8 at test1 ready]
00000000 CAPABILITY
* CAPABILITY IMAP4 IMAP4REV1 ACL NAMESPACE UIDPLUS IDLE LITERAL+ QUOTA 
ID MULTIAPPEND LISTEXT CHILDR
EN BINARY LOGIN-REFERRALS STARTTLS AUTH=LOGIN AUTH=PLAIN AUTH=CRAM-MD5 
AUTH=DIGEST-MD5 AUTH=MSN
00000000 OK completed
00000001 STARTTLS
00000001 OK begin TLS negotiation
00000002 CAPABILITY
* CAPABILITY IMAP4 IMAP4REV1 ACL NAMESPACE UIDPLUS IDLE LITERAL+ QUOTA 
ID MULTIAPPEND LISTEXT CHILDR
EN BINARY LOGIN-REFERRALS AUTH=LOGIN AUTH=PLAIN AUTH=CRAM-MD5 
AUTH=DIGEST-MD5 AUTH=MSN
00000002 OK completed
00000003 AUTHENTICATE PLAIN
+
{localhost/imap/user="postmaster"} password:
cG9zdG1hc3RlcgBwYXRyaWNrYgAxMjM0
00000003 NO SASL parameters are incorrect
%Retrying PLAIN authentication after SASL parameters are incorrect
00000004 AUTHENTICATE PLAIN
+
{localhost/imap/user="postmaster"} password:
----------

...any ideas?

Thanks,
Patrick Bennett

---

From: Mark Crispin <[email-masked]>
Date: Fri, 28 Jan 2005 09:52:20 -0800 (PST)

On Fri, 28 Jan 2005, Patrick Bennett wrote:
>  When using /authuser with Exchange I get the error 
> 'Can't do /authuser with this server.'

As you surmised, Exchange does not support it.

> I then set up a local test CommuniGate Pro server to try it.

Your test shows that Communigate Pro doesn't support it either; or at 
least you attempted to use an id that did not have administrative 
privileges.

These are server issues.  If it isn't supported in the server, there is no 
way that a client can offer the facility.  At least, unlike PROXYAUTH, you 
can ask the server vendors to support it and point to an RFC which 
describes it.

-- Mark --