merge with latest
[external/uw-imap-toolkit.git] / imap-2007e / c-client / auth_pla.c
1 /* ========================================================================
2  * Copyright 1988-2006 University of Washington
3  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * 
11  * ========================================================================
12  */
13
14 /*
15  * Program:     Plain authenticator
16  *
17  * Author:      Mark Crispin
18  *              Networks and Distributed Computing
19  *              Computing & Communications
20  *              University of Washington
21  *              Administration Building, AG-44
22  *              Seattle, WA  98195
23  *              Internet: MRC@CAC.Washington.EDU
24  *
25  * Date:        22 September 1998
26  * Last Edited: 30 August 2006
27  */
28 \f
29 long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
30                         char *service,NETMBX *mb,void *stream,
31                         unsigned long *trial,char *user);
32 char *auth_plain_server (authresponse_t responder,int argc,char *argv[]);
33
34 AUTHENTICATOR auth_pla = {
35   AU_AUTHUSER | AU_HIDE,        /* allow authuser, hidden */
36   "PLAIN",                      /* authenticator name */
37   NIL,                          /* always valid */
38   auth_plain_client,            /* client method */
39   auth_plain_server,            /* server method */
40   NIL                           /* next authenticator */
41 };
42 \f
43 /* Client authenticator
44  * Accepts: challenger function
45  *          responder function
46  *          SASL service name
47  *          parsed network mailbox structure
48  *          stream argument for functions
49  *          pointer to current trial count
50  *          returned user name
51  * Returns: T if success, NIL otherwise, number of trials incremented if retry
52  */
53
54 long auth_plain_client (authchallenge_t challenger,authrespond_t responder,
55                         char *service,NETMBX *mb,void *stream,
56                         unsigned long *trial,char *user)
57 {
58   char *u,pwd[MAILTMPLEN];
59   void *challenge;
60   unsigned long clen;
61   long ret = NIL;
62                                 /* snarl if not SSL/TLS session */
63   if (!mb->sslflag && !mb->tlsflag)
64     mm_log ("SECURITY PROBLEM: insecure server advertised AUTH=PLAIN",WARN);
65                                 /* get initial (empty) challenge */
66   if (challenge = (*challenger) (stream,&clen)) {
67     fs_give ((void **) &challenge);
68     pwd[0] = NIL;               /* prompt user if empty challenge */
69     mm_login (mb,user,pwd,*trial);
70
71     if (!pwd[0]) {              /* empty challenge or user requested abort */
72       (*responder) (stream,NIL,0);
73       *trial = 0;               /* cancel subsequent attempts */
74       ret = LONGT;              /* will get a BAD response back */
75     }
76
77     else if ((*responder) (stream,user,strlen (user)) &&
78              (challenge = (*challenger) (stream,&clen))) {
79       fs_give ((void **) &challenge);
80                                 /* send password */
81       if ((*responder) (stream,pwd,strlen (pwd))) {
82         if (challenge = (*challenger) (stream,&clen))
83           fs_give ((void **) &challenge);
84         else {
85           ++*trial;             /* can try again if necessary */
86           ret = LONGT;          /* check the authentication */
87         }
88       }
89     }
90
91     else {
92       unsigned long rlen = 
93         strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2;
94       char *response = (char *) fs_get (rlen);
95       char *t = response;       /* copy authorization id */
96
97         memset(response, 0x00, rlen);
98
99       if (mb->authuser[0]) for (u = user; *u; *t++ = *u++);
100       *t++ = '\0';              /* delimiting NUL */
101
102                                 /* copy authentication id */
103       for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++);
104       *t++ = '\0';              /* delimiting NUL */
105
106                                 /* copy password */
107       for (u = pwd; *u; *t++ = *u++);
108                                 /* send credentials */
109         
110       if ((*responder) (stream,response,rlen)) {
111         if (challenge = (*challenger) (stream,&clen))
112         {
113           fs_give ((void **) &challenge);
114         }
115         else {
116           ++*trial;             /* can try again if necessary */
117           ret = LONGT;          /* check the authentication */
118         }
119       }
120       memset (response,0,rlen); /* erase credentials */
121       fs_give ((void **) &response);
122     }
123   }
124   else
125   {
126         mm_log ("Enter section for handling emtpy challenge",WARN);
127     pwd[0] = NIL;               /* prompt user if empty challenge */
128
129         mm_login (mb,user,pwd,*trial);
130
131         if (pwd[0] == NULL) 
132     { /* empty challenge or user requested abort */
133       mm_log ("empty challenge or user requested abort",WARN);
134       (*responder) (stream,NIL,0);
135       *trial = 0;               /* cancel subsequent attempts */
136       ret = LONGT;              /* will get a BAD response back */
137     }
138     else 
139         {
140       unsigned long rlen = strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2;
141       char *response = (char *) fs_get (rlen);
142       char *t = response;       /* copy authorization id */
143
144           mm_log ("copy authorization id ",WARN);
145
146           if (mb->authuser[0]) 
147                 for (u = user; *u; *t++ = *u++);
148           *t++ = '\0';          /* delimiting NUL */
149                                         /* copy authentication id */
150       for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++);
151       *t++ = '\0';              /* delimiting NUL */
152                                         /* copy password */
153       for (u = pwd; *u; *t++ = *u++); /* send credentials */
154
155           if ((*responder)(stream,response,rlen)) 
156           {
157             mm_log ("response ",WARN);
158             if (challenge = (*challenger) (stream,&clen))
159               fs_give ((void **) &challenge);
160             else 
161             {
162               mm_log ("Second empty challege  ",WARN);
163               ++*trial;         /* can try again if necessary */
164               ret = LONGT;              /* check the authentication */
165             }
166       }
167       memset (response,0,rlen); /* erase credentials */
168       fs_give ((void **) &response);
169     }
170         
171   }
172
173   memset (pwd,0,MAILTMPLEN);    /* erase password */
174   if (!ret) *trial = 65535;     /* don't retry if bad protocol */
175   return ret;
176 }
177 \f
178 /* Server authenticator
179  * Accepts: responder function
180  *          argument count
181  *          argument vector
182  * Returns: authenticated user name or NIL
183  */
184
185 char *auth_plain_server (authresponse_t responder,int argc,char *argv[])
186 {
187   char *ret = NIL;
188   char *user,*aid,*pass;
189   unsigned long len;
190                                 /* get user name */
191   if (aid = (*responder) ("",0,&len)) {
192                                 /* note: responders null-terminate */
193     if ((((unsigned long) ((user = aid + strlen (aid) + 1) - aid)) < len) &&
194         (((unsigned long) ((pass = user + strlen (user) + 1) - aid)) < len) &&
195         (((unsigned long) ((pass + strlen (pass)) - aid)) == len) &&
196         (*aid ? server_login (aid,pass,user,argc,argv) :
197          server_login (user,pass,NIL,argc,argv))) ret = myusername ();
198     fs_give ((void **) &aid);
199   }
200   return ret;
201 }