Timsieved valid commands

Mark Keasling mark at air.co.jp
Tue Nov 19 22:45:55 EST 2002


Hi,

On Tue, 19 Nov 2002 21:20:57 -0500, Su Li <sli at rim.net> wrote...
> Thanks a lot Mark and Ken,
> 
> I am writing a C++ client to log into Sieve 2000 port. Can you send me the C++/C code for base64 encode? So what I need to do to login to Sieve should be like:
> 
> C: AUTHENTICATE "PLAIN" {21+}
> C: <base64 encoded authname and username>
> S: password?
> C: <base64 encode password>
> S: OK loged in
> 
> Is that right?
> 
No.  PLAIN works differently than LOGIN.  PLAIN does not use base64 encoding.
In your C++ client, you should use the SASL libraries to do authentication
as Ken Murchison suggests.

However, for testing purposes you may still want to connect to the timsieved
by telnet.  In that case using AUTHENTICATE "LOGIN" is easiest way to login
to or authenticate with the server.  To be able to use AUTHENTICATE "LOGIN",
you need to have configured sasl with the "--enable-login" option.  After
installation you should have these files in /usr/lib/sasl2:
    liblogin.la
    liblogin.so
    liblogin.so.2
    liblogin.so.2.0.7

Connecting to timsieved will yield a response similar to:

$ telnet sievehost 2000
S: "IMPLEMENTATION" "Cyrus timsieved v1.1.0"
S: "SASL" "PLAIN OTP LOGIN GSSAPI DIGEST-MD5 CRAM-MD5"
S: "SIEVE" "fileinto reject envelope vacation imapflags notify subaddress relational regex"
S: OK

where LOGIN is listed in "SASL" line.  At this point you are able to use the
AUTHENTICATE "LOGIN" command as follows:

C: AUTHENTICATE "LOGIN"
S: {12}
S: VXNlcm5hbWU6
C: {8+}
C: b64data=
S: {12}
S: UGFzc3dvcmQ6
C: {8+}
C: b64data=
S: OK

The base64 strings that the server returned are "VXNlcm5hbWU6" which is
"Username:" and "UGFzc3dvcmQ6" which is "Password:".  The theory is that
these strings should be displayed to the user.  The "{8+}" line tells the
server how much base64 data to expect.

Quoting the base64 strings also works:

C: AUTHENTICATE "LOGIN"
S: {12}
S: VXNlcm5hbWU6
C: "b64data="
S: {12}
S: UGFzc3dvcmQ6
C: "b64data="
S: OK

To use AUTHENTICATE "PLAIN" you have to able to enter a '\0' in the data
sent with the command which is not possible as far as I know when you are
connecting with telnet.

In C you could do something like the following to send a plain authentication
command:

    // example untested code.  It probably contains errors, doesn't compile
    // and/or does not work as expected.

    int socketfd = -1 ;
    int sentcommand = 0 ;
    char * authname = NULL, * username = NULL, * password = NULL ;
    char * databuffer = NULL, * commandbuffer = NULL ;
    unsigned int datalength = 0 ;
    const char * const command = "AUTHENTICATE \"PLAIN\" {%u+}\r\n" ;

    // set socketfd to the timseived connection file descriptor.
    // set the variables authname, username, password to non null.
    // empty string is ok.

    datalength = 2 + strlen( authname ) + strlen( username ) + strlen( password ) ;
    comandbuffer = (char *) malloc( 64 + strlen( command )) ; // guestimate
    if( commandbuffer )
    {
        sprintf( commandbuffer, command, datalength ) ;
        databuffer = (char *) malloc( datalength + 1 ) ; // add one for terminator
        if( databuffer && ( -1 != socketfd ))
        {
            // databuffer contains embedded null characters.
            sprintf( databuffer, "%s\0%s\0%s", authname, username, password ) ;
            write( socketfd, (void *) commandbuffer, strlen( commandbuffer ) ;
            write( socketfd, (void *) databuffer, (size_t) length ) ;
            sentcommand = 1 ;
         }
    }
    if( commandbuffer ) free( (void *) commandbuffer ) ;
    if( databuffer )    free( (void *) databuffer ) ;
    if( sentcommand )
    {
        // read server response...
    }
    else
    {
        // handle error...
    }

However, using the SASL library is a better option for coding.

Regards,
Mark Keasling <mark at air.co.jp>





More information about the Info-cyrus mailing list