~ubuntu-branches/ubuntu/oneiric/jabberd2/oneiric-security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
diff -u /usr/local/src/jabberd-2.0s6/c2s/c2s.c c2s/c2s.c
--- /usr/local/src/jabberd-2.0s6/c2s/c2s.c	Thu Dec 23 19:42:29 2004
+++ c2s/c2s.c	Thu Dec 23 19:41:20 2004
@@ -20,6 +20,65 @@
 
 #include "c2s.h"
 
+/*
+ * M.Bootsma, LogicaCMG Hoofddorp, Netherlands
+ * October 2004
+ *
+ * Added a patch for flash:stream support
+ *
+ * Flash is not 100% compatible with the XML stream standard:
+ * 1. it terminates every XML message with a '\0'
+ * 2. it terminates the stream header with a /
+ *    (this would close the stream)
+ * 3. it starts the stream with a flash:stream header instead of
+ *    a stream:stream header.
+ *
+ * The patch checks the first message of a starting session stream
+ * for any '\0'. If found it flags the session as a Flash session
+ * and replases the complete header with a Jabber compatible
+ * header.
+ * After that every incoming message is filtered and '\0' is 
+ * replaced with ' '.
+ * For every outgoing message, a '\0' is appended and the response
+ * of the header is replaced for a flash friendly version
+ *
+ * The whole flash patch can be switched off by undefining CP2005_FLASH_PATCH
+ * in config.h(.in)
+ */
+
+#ifdef CP2005_FLASH_PATCH
+
+#define FLASH_BUFFER_SIZE 256
+
+static const char caStreamHeader [] = "<?xml version='1.0'?><stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' to='%s' >";
+static const char caFlashHeader []  = "<?xml version='1.0'?><flash:stream xmlns:flash='http://www.jabber.com/streams/flash' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client' from='%s' id='%s' />";
+
+static void ExtractValue(char *pMessage, char *pVariable, char *pValue) { 
+    int iLen; 
+    char *p;
+    char *pEnd;
+
+    /*
+     * extract the value of an attribute from a XML message
+     * eg: <.... id='1234567890' ....> returns 1234567890
+     */
+
+    p = strstr(pMessage, pVariable);
+    if (p != NULL) {
+        p += (strlen(pVariable) + 1);
+        /* find end of value, search for closing ' or " */
+        pEnd = strchr(p, p [-1]);
+        iLen = pEnd - p;
+        if (iLen < FLASH_BUFFER_SIZE) {
+            memcpy(pValue, p, iLen);
+            pValue[iLen] = '\0';
+            log_debug(ZONE, "++++ Extracted Var %s: [%s]\n", pVariable, pValue);
+        }
+    }
+}
+#endif
+
+
 static int _c2s_client_sx_callback(sx_t s, sx_event_t e, void *data, void *arg) {
     sess_t sess = (sess_t) arg;
     sx_buf_t buf = (sx_buf_t) data;
@@ -28,6 +93,12 @@
     nad_t nad;
     char root[9];
 
+#ifdef CP2005_FLASH_PATCH
+    char *p, *pEnd;
+    char caHost[FLASH_BUFFER_SIZE];
+    char caID[FLASH_BUFFER_SIZE];
+#endif
+
     switch(e) {
         case event_WANT_READ:
             log_debug(ZONE, "want read");
@@ -94,14 +165,74 @@
                 return -1;
             }
 
-            log_debug(ZONE, "read %d bytes", len);
-
             buf->len = len;
 
+#ifdef CP2005_FLASH_PATCH
+            /* check for 0 bytes in the first packet
+             * if found it must be a flash client
+             * remove any 0 in the data and
+             * the / that ends the <?xml... header
+             */
+
+            pEnd = &buf->data[len];
+
+            if (sess->s->state == state_NONE) {
+                /* stream is new, look for 0 bytes */
+                p = memchr(buf->data, '\0', buf->len);
+                if ((p != NULL) && (p < pEnd)) {
+                    log_debug(ZONE, "++++ Flash Stream detected\n%.*s", buf->len, buf->data);
+                    sess->flash_client = 1;
+
+                    /* extract destination host */
+                    ExtractValue(buf->data, "to=", caHost);
+
+                    /* create normal stream:stream header, resize data buffer first */
+                    _sx_buffer_alloc_margin(buf, 0, sizeof(caStreamHeader) + strlen(caHost) + 8);
+                    sprintf(buf->data, caStreamHeader, caHost);
+                    buf->len = strlen(buf->data);
+
+                    log_debug(ZONE, "++++ Converted to\n%.*s", buf->len, buf->data);
+                }
+            }
+
+            /* Check all other messages in the stream to remove \0's etc */
+            if (sess->flash_client) 
+                /* remove 0's from flash packets */
+                for (p = buf->data; p < pEnd; p++)
+                    if (*p == '\0')
+                        *p = ' ';
+#endif
+            log_debug(ZONE, "read %d bytes", len);
+
             return len;
 
         case event_WRITE:
             log_debug(ZONE, "writing to %d", sess->fd->fd);
+
+#ifdef CP2005_FLASH_PATCH
+            if (sess->flash_client) {
+                /* look for the header <? xml ...*/
+                if (strncmp(buf->data, "<?xml ", 6) == 0) {
+                    /* replace normal stream header with flash friendly header */
+                    log_debug(ZONE, "++++ Found <?xml..., \n%.*s", buf->len, buf->data);
+
+                    /* extract id from id="123456567778765" or id='45454545454' */
+                    ExtractValue(buf->data, "from=", caHost);
+                    ExtractValue(buf->data, "id=", caID);
+
+                    /* create flash:stream header, realloc buffer first */
+                    _sx_buffer_alloc_margin(buf, 0, sizeof(caFlashHeader) + strlen(caHost) + strlen(caID) + 8);
+                    sprintf(buf->data, caFlashHeader, caHost, caID);
+                    buf->len = strlen(buf->data);
+
+                    log_debug(ZONE, "++++ Converted to %s", buf->data);
+                }
+
+                /* add a 0 to flash packets */
+                buf->data[buf->len] = '\0';
+                buf->len++;
+            }
+#endif
 
             len = send(sess->fd->fd, buf->data, buf->len, 0);
             if(len >= 0) {
diff -u /usr/local/src/jabberd-2.0s6/c2s/c2s.h c2s/c2s.h
--- /usr/local/src/jabberd-2.0s6/c2s/c2s.h	Tue Dec  7 18:38:05 2004
+++ c2s/c2s.h	Thu Dec 23 19:23:47 2004
@@ -62,6 +62,10 @@
     int                 bound;
     int                 active;
 
+#ifdef CP2005_FLASH_PATCH
+    int                 flash_client;
+#endif
+
     nad_t               result;
 
     int                 sasl_authd;     /* 1 = they did a sasl auth */