/* Add a listener. Check for any mount information that states any * authentication to be used. */ int auth_add_listener (const char *mount, client_t *client) { int ret = 0, need_auth = 1; ice_config_t *config = config_get_config(); mount_proxy *mountinfo = config_find_mount (config, mount); if (client->flags & CLIENT_AUTHENTICATED) need_auth = 0; else { const char *range = httpp_getvar (client->parser, "range"); if (range) { uint64_t pos1 = 0, pos2 = (uint64_t)-1; if (strncmp (range, "bytes=", 6) == 0) { if (sscanf (range+6, "-%" SCNuMAX, &pos2) < 1) if (sscanf (range+6, "%" SCNuMAX "-%" SCNuMAX, &pos1, &pos2) < 1) pos2 = 0; } else pos2 = 0; if (pos2 > 0 && pos1 < pos2) { client->intro_offset = pos1; client->connection.discon.offset = pos2; client->flags |= CLIENT_RANGE_END; if (pos2 - pos1 < 10) need_auth = 0; // avoid auth check if range is very small, player hack } else WARN2 ("client range invalid (%" PRIu64 ", %" PRIu64 "), ignoring", pos1, pos2); } } if (client->parser->req_type == httpp_req_head) { client->flags &= ~CLIENT_AUTHENTICATED; need_auth = 0; } if (need_auth) { if (mountinfo) { auth_t *auth = mountinfo->auth; if (mountinfo->skip_accesslog) client->flags |= CLIENT_SKIP_ACCESSLOG; if (mountinfo->ban_client) { if (mountinfo->ban_client < 0) client->flags |= CLIENT_IP_BAN_LIFT; connection_add_banned_ip (client->connection.ip, mountinfo->ban_client); } if (mountinfo->no_mount) { config_release_config (); return client_send_403 (client, "mountpoint unavailable"); } if (mountinfo->redirect) { char buffer [4096] = ""; unsigned int len = sizeof buffer; if (util_expand_pattern (mount, mountinfo->redirect, buffer, &len) == 0) { config_release_config (); return client_send_302 (client, buffer); } WARN3 ("failed to expand %s on %s for %s", mountinfo->redirect, mountinfo->mountname, mount); return client_send_501 (client); } do { if (auth == NULL) break; if ((auth->flags & AUTH_RUNNING) == 0) break; if (auth->pending_count > 400) { if (auth->flags & AUTH_SKIP_IF_SLOW) break; config_release_config (); WARN0 ("too many clients awaiting authentication"); if (global.new_connections_slowdown < 10) global.new_connections_slowdown++; return client_send_403 (client, "busy, please try again later"); } if (auth->authenticate) { auth_client *auth_user = auth_client_setup (mount, client); auth_user->process = auth_new_listener; client->flags &= ~CLIENT_ACTIVE; DEBUG0 ("adding client for authentication"); queue_auth_client (auth_user, mountinfo); config_release_config (); return 0; } } while (0); } else { if (strcmp (mount, "/admin/streams") == 0) { config_release_config (); return client_send_401 (client, NULL); } } } ret = add_authenticated_listener (mount, mountinfo, client); config_release_config (); return ret; }
static int http_client_request (client_t *client) { refbuf_t *refbuf = client->shared_data; int remaining = PER_CLIENT_REFBUF_SIZE - 1 - refbuf->len, ret = -1; if (remaining && client->connection.discon_time > client->worker->current_time.tv_sec) { char *buf = refbuf->data + refbuf->len; ret = client_read_bytes (client, buf, remaining); if (ret > 0) { char *ptr; buf [ret] = '\0'; refbuf->len += ret; if (memcmp (refbuf->data, "<policy-file-request/>", 23) == 0) { fbinfo fb; memset (&fb, 0, sizeof(fb)); fb.mount = "/flashpolicy"; fb.flags = FS_USE_ADMIN; fb.type = FORMAT_TYPE_UNDEFINED; client->respcode = 200; refbuf_release (refbuf); client->shared_data = NULL; client->check_buffer = format_generic_write_to_client; return fserve_setup_client_fb (client, &fb); } /* find a blank line */ do { buf = refbuf->data; ptr = strstr (buf, "\r\n\r\n"); if (ptr) { ptr += 4; break; } ptr = strstr (buf, "\n\n"); if (ptr) { ptr += 2; break; } ptr = strstr (buf, "\r\r\n\r\r\n"); if (ptr) { ptr += 6; break; } client->schedule_ms = client->worker->time_ms + 100; return 0; } while (0); client->refbuf = client->shared_data; client->shared_data = NULL; client->connection.discon_time = 0; client->parser = httpp_create_parser(); httpp_initialize (client->parser, NULL); if (httpp_parse (client->parser, refbuf->data, refbuf->len)) { if (useragents.filename) { const char *agent = httpp_getvar (client->parser, "user-agent"); if (agent && search_cached_pattern (&useragents, agent) > 0) { INFO2 ("dropping client at %s because useragent is %s", client->connection.ip, agent); return -1; } } /* headers now parsed, make sure any sent content is next */ if (strcmp("ICE", httpp_getvar (client->parser, HTTPP_VAR_PROTOCOL)) && strcmp("HTTP", httpp_getvar (client->parser, HTTPP_VAR_PROTOCOL))) { ERROR0("Bad HTTP protocol detected"); return -1; } auth_check_http (client); switch (client->parser->req_type) { case httpp_req_get: refbuf->len = PER_CLIENT_REFBUF_SIZE; client->ops = &http_req_get_ops; break; case httpp_req_source: client->pos = ptr - refbuf->data; client->ops = &http_req_source_ops; break; case httpp_req_stats: refbuf->len = PER_CLIENT_REFBUF_SIZE; client->ops = &http_req_stats_ops; break; case httpp_req_options: return client_send_options (client); default: WARN1("unhandled request type from %s", client->connection.ip); return client_send_501 (client); } client->counter = 0; return client->ops->process(client); } /* invalid http request */ return -1; } if (ret && client->connection.error == 0) { /* scale up the retry time, very short initially, usual case */ uint64_t diff = client->worker->time_ms - client->counter; diff >>= 1; if (diff > 200) diff = 200; client->schedule_ms = client->worker->time_ms + 6 + diff; return 0; }