~ubuntu-branches/ubuntu/vivid/sslh/vivid-proposed

« back to all changes in this revision

Viewing changes to probe.c

  • Committer: Package Import Robot
  • Author(s): Guillaume Delacour
  • Date: 2014-08-07 00:06:06 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20140807000606-y1tg7j8i5t7d4drr
Tags: 1.16-1
* New upstream release: fix some startup problem when interfaces are not
  ready at boot time (IP_FREEBIND support when available) and can use libcap
  for transparent mode
* Enable libcap and libwrap support at build time
* Enable dpkg-buildflags: Drop hardening-wrapper Build-Depends and use
  DEB_BUILD_HARDENING instead of DEB_BUILD_MAINT_OPTIONS
* Remove old .gitignore as upstream has one too
* debian/sslh.tmpfile: Create /run/sslh for systemd as root because sslh
  write its pid before dropping privileges (Closes: #740560)
* debian/patches/disable_ip_freebind_test.diff: Remove "Can't bind address"
  upstream test because IP_FREEBIND is now enabled upstream
* debian/docs: upstream README is now README.md
* debian/rules:
  + use DESTDIR in addition of PREFIX as upstream change Makefile
* Refresh debian/patches/disable_valgrind_launch.diff due to upstream
  changes
* Stop service in case of purge (to be able to remove the user too)
* Use DEB_BUILD_OPTIONS to speed the build
* debian/patches/fixed_version.diff: Fix the version of binaries based on
  debian/changelog (instead of relying on git)
* Update Description as sslh is not only a ssl/ssh multiplexer but a
  protocol multiplexer

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
/* Sets the protocol name to connect to in case of timeout */
64
64
void set_ontimeout(const char* name)
65
65
{
66
 
    asprintf(&on_timeout, "%s", name);
 
66
    int res = asprintf(&on_timeout, "%s", name);
 
67
    CHECK_RES_DIE(res, "asprintf");
67
68
}
68
69
 
69
70
/* Returns the protocol to connect to in case of timeout; 
124
125
/* Is the buffer the beginning of an SSH connection? */
125
126
static int is_ssh_protocol(const char *p, int len, struct proto *proto)
126
127
{
127
 
    if (!strncmp(p, "SSH-", 4)) {
128
 
        return 1;
129
 
    }
130
 
    return 0;
 
128
    if (len < 4)
 
129
        return PROBE_AGAIN;
 
130
 
 
131
    return !strncmp(p, "SSH-", 4);
131
132
}
132
133
 
133
134
/* Is the buffer the beginning of an OpenVPN connection?
142
143
 */
143
144
static int is_openvpn_protocol (const char*p,int len, struct proto *proto)
144
145
{
145
 
    int packet_len = ntohs(*(uint16_t*)p);
146
 
 
 
146
    int packet_len;
 
147
 
 
148
    if (len < 2)
 
149
        return PROBE_AGAIN;
 
150
 
 
151
    packet_len = ntohs(*(uint16_t*)p);
147
152
    return packet_len == len - 2;
148
153
}
149
154
 
152
157
 * */
153
158
static int is_tinc_protocol( const char *p, int len, struct proto *proto)
154
159
{
 
160
    if (len < 2)
 
161
        return PROBE_AGAIN;
 
162
 
155
163
    return !strncmp(p, "0 ", 2);
156
164
}
157
165
 
161
169
 * */
162
170
static int is_xmpp_protocol( const char *p, int len, struct proto *proto)
163
171
{
164
 
    return strstr(p, "jabber") ? 1 : 0;
 
172
    if (len < 6)
 
173
        return PROBE_AGAIN;
 
174
 
 
175
    return memmem(p, len, "jabber", 6) ? 1 : 0;
165
176
}
166
177
 
167
 
static int probe_http_method(const char *p, const char *opt)
 
178
static int probe_http_method(const char *p, int len, const char *opt)
168
179
{
169
 
    return !strcmp(p, opt);
 
180
    if (len < strlen(opt))
 
181
        return PROBE_AGAIN;
 
182
 
 
183
    return !strncmp(p, opt, len);
170
184
}
171
185
 
172
186
/* Is the buffer the beginning of an HTTP connection?  */
173
187
static int is_http_protocol(const char *p, int len, struct proto *proto)
174
188
{
 
189
    int res;
175
190
    /* If it's got HTTP in the request (HTTP/1.1) then it's HTTP */
176
 
    if (strstr(p, "HTTP"))
177
 
        return 1;
 
191
    if (memmem(p, len, "HTTP", 4))
 
192
        return PROBE_MATCH;
 
193
 
 
194
#define PROBE_HTTP_METHOD(opt) if ((res = probe_http_method(p, len, opt)) != PROBE_NEXT) return res
178
195
 
179
196
    /* Otherwise it could be HTTP/1.0 without version: check if it's got an
180
197
     * HTTP method (RFC2616 5.1.1) */
181
 
    probe_http_method(p, "OPTIONS");
182
 
    probe_http_method(p, "GET");
183
 
    probe_http_method(p, "HEAD");
184
 
    probe_http_method(p, "POST");
185
 
    probe_http_method(p, "PUT");
186
 
    probe_http_method(p, "DELETE");
187
 
    probe_http_method(p, "TRACE");
188
 
    probe_http_method(p, "CONNECT");
189
 
 
190
 
    return 0;
 
198
    PROBE_HTTP_METHOD("OPTIONS");
 
199
    PROBE_HTTP_METHOD("GET");
 
200
    PROBE_HTTP_METHOD("HEAD");
 
201
    PROBE_HTTP_METHOD("POST");
 
202
    PROBE_HTTP_METHOD("PUT");
 
203
    PROBE_HTTP_METHOD("DELETE");
 
204
    PROBE_HTTP_METHOD("TRACE");
 
205
    PROBE_HTTP_METHOD("CONNECT");
 
206
 
 
207
#undef PROBE_HTTP_METHOD
 
208
 
 
209
    return PROBE_NEXT;
191
210
}
192
211
 
193
212
static int is_tls_protocol(const char *p, int len, struct proto *proto)
194
213
{
 
214
    if (len < 3)
 
215
        return PROBE_AGAIN;
 
216
 
195
217
    /* TLS packet starts with a record "Hello" (0x16), followed by version
196
218
     * (0x03 0x00-0x03) (RFC6101 A.1)
197
219
     * This means we reject SSLv2 and lower, which is actually a good thing (RFC6176)
201
223
 
202
224
static int regex_probe(const char *p, int len, struct proto *proto)
203
225
{
204
 
    regex_t** probe_list = (regex_t**)(proto->data);
205
 
    int i=0;
206
 
 
207
 
    while (probe_list[i]) {
208
 
        if (!regexec(probe_list[i], p, 0, NULL, 0)) {
209
 
            return 1;
210
 
        }
211
 
        i++;
212
 
    }
213
 
    return 0;
 
226
    regex_t **probe = proto->data;
 
227
    regmatch_t pos = { 0, len };
 
228
 
 
229
    for (; *probe && regexec(*probe, p, 0, &pos, REG_STARTEND); probe++)
 
230
        /* try them all */;
 
231
 
 
232
    return (probe != NULL);
214
233
}
215
234
 
216
235
/* 
217
236
 * Read the beginning of data coming from the client connection and check if
218
 
 * it's a known protocol. Then leave the data on the defered
219
 
 * write buffer of the connection and returns a pointer to the protocol
220
 
 * structure
 
237
 * it's a known protocol. 
 
238
 * Return PROBE_AGAIN if not enough data, or PROBE_MATCH if it succeeded in
 
239
 * which case cnx->proto is set to the appropriate protocol.
221
240
 */
222
 
struct proto* probe_client_protocol(struct connection *cnx)
 
241
int probe_client_protocol(struct connection *cnx)
223
242
{
224
243
    char buffer[BUFSIZ];
225
244
    struct proto *p;
232
251
     * function does not have to deal with a specific  failure condition (the
233
252
     * connection will just fail later normally). */
234
253
    if (n > 0) {
 
254
        int res = PROBE_NEXT;
 
255
 
235
256
        defer_write(&cnx->q[1], buffer, n);
236
257
 
237
 
        for (p = protocols; p; p = p->next) {
 
258
        for (p = cnx->proto; p && res == PROBE_NEXT; p = p->next) {
238
259
            if (! p->probe) continue;
239
260
            if (verbose) fprintf(stderr, "probing for %s\n", p->description);
240
 
            if (p->probe(buffer, n, p)) {
241
 
                if (verbose) fprintf(stderr, "probe %s successful\n", p->description);
242
 
                return p;
243
 
            }
 
261
 
 
262
            cnx->proto = p;
 
263
            res = p->probe(cnx->q[1].begin_deferred_data, cnx->q[1].deferred_data_size, p);
244
264
        }
 
265
        if (res != PROBE_NEXT)
 
266
            return res;
245
267
    }
246
268
 
247
269
    if (verbose) 
251
273
 
252
274
    /* If none worked, return the first one affected (that's completely
253
275
     * arbitrary) */
254
 
    return protocols;
 
276
    cnx->proto = protocols;
 
277
    return PROBE_MATCH;
255
278
}
256
279
 
257
280
/* Returns the structure for specified protocol or NULL if not found */