Login and logout queue events are processed
[citadel.git] / citadel / modules / jabber / xmpp_sasl_service.c
1 /*
2  * $Id$ 
3  *
4  * Barebones SASL authentication service for XMPP (Jabber) clients.
5  *
6  * Why barebones?  Because RFC3920 says we "must" support DIGEST-MD5 but
7  * we only support PLAIN.
8  *
9  * Copyright (c) 2007 by Art Cancro
10  * This code is released under the terms of the GNU General Public License.
11  *
12  */
13
14 #include "sysdep.h"
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <signal.h>
20 #include <pwd.h>
21 #include <errno.h>
22 #include <sys/types.h>
23
24 #if TIME_WITH_SYS_TIME
25 # include <sys/time.h>
26 # include <time.h>
27 #else
28 # if HAVE_SYS_TIME_H
29 #  include <sys/time.h>
30 # else
31 #  include <time.h>
32 # endif
33 #endif
34
35 #include <sys/wait.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <ctype.h>
39 #include <libcitadel.h>
40 #include "citadel.h"
41 #include "server.h"
42 #include "citserver.h"
43 #include "support.h"
44 #include "config.h"
45 #include "user_ops.h"
46 #include "internet_addressing.h"
47 #include "md5.h"
48 #include "ctdl_module.h"
49
50 #ifdef HAVE_EXPAT
51 #include <expat.h>
52 #include "serv_xmpp.h"
53
54
55 /*
56  * PLAIN authentication.  Returns zero on success, nonzero on failure.
57  */
58 int xmpp_auth_plain(char *authstring)
59 {
60         char decoded_authstring[1024];
61         char ident[256];
62         char user[256];
63         char pass[256];
64         int result;
65
66         CtdlDecodeBase64(decoded_authstring, authstring, strlen(authstring));
67         safestrncpy(ident, decoded_authstring, sizeof ident);
68         safestrncpy(user, &decoded_authstring[strlen(ident) + 1], sizeof user);
69         safestrncpy(pass, &decoded_authstring[strlen(ident) + strlen(user) + 2], sizeof pass);
70
71         if (!IsEmptyStr(ident)) {
72                 result = CtdlLoginExistingUser(user, ident);
73         }
74         else {
75                 result = CtdlLoginExistingUser(NULL, user);
76         }
77
78         if (result == login_ok) {
79                 if (CtdlTryPassword(pass) == pass_ok) {
80                         return(0);                              /* success */
81                 }
82         }
83
84         return(1);                                              /* failure */
85 }
86
87
88 /*
89  * Output the list of SASL mechanisms offered by this stream.
90  */
91 void xmpp_output_auth_mechs(void) {
92         cprintf("<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
93         cprintf("<mechanism>PLAIN</mechanism>");
94         cprintf("</mechanisms>");
95 }
96
97 /*
98  * Here we go ... client is trying to authenticate.
99  */
100 void xmpp_sasl_auth(char *sasl_auth_mech, char *authstring) {
101
102         if (strcasecmp(sasl_auth_mech, "PLAIN")) {
103                 cprintf("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
104                 cprintf("<invalid-mechanism/>");
105                 cprintf("</failure>");
106                 return;
107         }
108
109         if (CC->logged_in) logout(CC);  /* Client may try to log in twice.  Handle this. */
110
111         if (xmpp_auth_plain(authstring) == 0) {
112                 cprintf("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>");
113         }
114
115         else {
116                 cprintf("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
117                 cprintf("<not-authorized/>");
118                 cprintf("</failure>");
119         }
120 }
121
122 #endif  /* HAVE_EXPAT */