Ejemplo n.º 1
0
static void handle_set_parameter(rtsp_conn_info *conn,
                                 rtsp_message *req, rtsp_message *resp) {
    if (!req->contentlength)
        debug(1, "received empty SET_PARAMETER request\n");

    char *ct = msg_get_header(req, "Content-Type");

    if (ct) {
        debug(2, "SET_PARAMETER Content-Type: %s\n", ct);

        if (!strncmp(ct, "application/x-dmap-tagged", 25)) {
            debug(1, "received metadata tags in SET_PARAMETER request\n");

            handle_set_parameter_metadata(conn, req, resp);
        } else if (!strncmp(ct, "image/jpeg", 10) || !strncmp(ct, "image/png", 9)) {
            debug(1, "received image in SET_PARAMETER request\n");

            handle_set_parameter_coverart(conn, req, resp);
         } else if (!strncmp(ct, "image/none", 10)) {
            debug(1, "received empty image in SET_PARAMETER request\n");

            handle_set_parameter_coverart_empty(conn, req, resp);
         } else if (!strncmp(ct, "text/parameters", 15)) {
            debug(1, "received parameters in SET_PARAMETER request\n");

            handle_set_parameter_parameter(conn, req, resp);
        } else {
            debug(1, "received unknown Content-Type %s in SET_PARAMETER request\n", ct);
        }
    } else {
        debug(1, "missing Content-Type header in SET_PARAMETER request\n");
    }

    resp->respcode = 200;
}
Ejemplo n.º 2
0
static void apple_challenge(int fd, rtsp_message *req, rtsp_message *resp) {
    char *hdr = msg_get_header(req, "Apple-Challenge");
    if (!hdr)
        return;

    SOCKADDR fdsa;
    socklen_t sa_len = sizeof(fdsa);
    getsockname(fd, (struct sockaddr*)&fdsa, &sa_len);

    int chall_len;
    uint8_t *chall = base64_dec(hdr, &chall_len);
    uint8_t buf[48], *bp = buf;
    int i;
    memset(buf, 0, sizeof(buf));

    if (chall_len > 16) {
        warn("oversized Apple-Challenge!");
        free(chall);
        return;
    }
    memcpy(bp, chall, chall_len);
    free(chall);
    bp += chall_len;

#ifdef AF_INET6
    if (fdsa.SAFAMILY == AF_INET6) {
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)(&fdsa);
        memcpy(bp, sa6->sin6_addr.s6_addr, 16);
        bp += 16;
    } else
#endif
    {
        struct sockaddr_in *sa = (struct sockaddr_in*)(&fdsa);
        memcpy(bp, &sa->sin_addr.s_addr, 4);
        bp += 4;
    }

    for (i=0; i<6; i++)
        *bp++ = config.hw_addr[i];

    int buflen, resplen;
    buflen = bp-buf;
    if (buflen < 0x20)
        buflen = 0x20;

    uint8_t *challresp = rsa_apply(buf, buflen, &resplen, RSA_MODE_AUTH);
    char *encoded = base64_enc(challresp, resplen);

    // strip the padding.
    char *padding = strchr(encoded, '=');
    if (padding)
        *padding = 0;

    msg_add_header(resp, "Apple-Response", encoded);
    free(challresp);
    free(encoded);
}
Ejemplo n.º 3
0
static void *rtsp_conversation_thread_func(void *pconn) {
    // SIGUSR1 is used to interrupt this thread if blocked for read
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);
    pthread_sigmask(SIG_UNBLOCK, &set, NULL);

    rtsp_conn_info *conn = pconn;

    rtsp_message *req, *resp;
    char *hdr, *auth_nonce = NULL;
    while ((req = rtsp_read_request(conn->fd))) {
        resp = msg_init();
        resp->respcode = 400;

        apple_challenge(conn->fd, req, resp);
        hdr = msg_get_header(req, "CSeq");
        if (hdr)
            msg_add_header(resp, "CSeq", hdr);
        msg_add_header(resp, "Audio-Jack-Status", "connected; type=analog");

        if (rtsp_auth(&auth_nonce, req, resp))
            goto respond;

        struct method_handler *mh;
        for (mh=method_handlers; mh->method; mh++) {
            if (!strcmp(mh->method, req->method)) {
                mh->handler(conn, req, resp);
                break;
            }
        }

respond:
        msg_write_response(conn->fd, resp);
        msg_free(req);
        msg_free(resp);
    }

    debug(1, "closing RTSP connection\n");
    if (conn->fd > 0)
        close(conn->fd);
    if (rtsp_playing()) {
        rtp_shutdown();
        debug(1, "stop player\n");
        player_stop();
        debug(1, "player stoped\n");
        please_shutdown = 0;
        pthread_mutex_unlock(&playing_mutex);
    }
    if (auth_nonce)
        free(auth_nonce);
    conn->running = 0;
    debug(2, "terminating RTSP thread\n");
    return NULL;
}
Ejemplo n.º 4
0
static int msg_handle_line(rtsp_message **pmsg, char *line) {
    rtsp_message *msg = *pmsg;

    if (!msg) {
        msg = msg_init();
        *pmsg = msg;
        char *sp, *p;

        debug(1, "received request: %s\n", line);

        p = strtok_r(line, " ", &sp);
        if (!p)
            goto fail;
        strncpy(msg->method, p, sizeof(msg->method)-1);

        p = strtok_r(NULL, " ", &sp);
        if (!p)
            goto fail;

        p = strtok_r(NULL, " ", &sp);
        if (!p)
            goto fail;
        if (strcmp(p, "RTSP/1.0"))
            goto fail;

        return -1;
    }

    if (strlen(line)) {
        char *p;
        p = strstr(line, ": ");
        if (!p) {
            warn("bad header: >>%s<<", line);
            goto fail;
        }
        *p = 0;
        p += 2;
        msg_add_header(msg, line, p);
        debug(2, "    %s: %s\n", line, p);
        return -1;
    } else {
        char *cl = msg_get_header(msg, "Content-Length");
        if (cl)
            return atoi(cl);
        else
            return 0;
    }

fail:
    *pmsg = NULL;
    msg_free(msg);
    return 0;
}
Ejemplo n.º 5
0
static void handle_set_parameter_coverart(rtsp_conn_info *conn,
                                          rtsp_message *req, rtsp_message *resp) {
    char *cp = req->content;
    int cl = req->contentlength;

    char *ct = msg_get_header(req, "Content-Type");

    if (!strncmp(ct, "image/jpeg", 10)) {
        player_cover_image(cp, cl, "jpg");
    } 

    if (!strncmp(ct, "image/png", 9)) {
        player_cover_image(cp, cl, "png");
    }    
}
Ejemplo n.º 6
0
static void handle_setup(rtsp_conn_info *conn,
                         rtsp_message *req, rtsp_message *resp) {
    int cport, tport;
    char *hdr = msg_get_header(req, "Transport");
    if (!hdr)
        return;

    char *p;
    p = strstr(hdr, "control_port=");
    if (!p)
        return;
    p = strchr(p, '=') + 1;
    cport = atoi(p);

    p = strstr(hdr, "timing_port=");
    if (!p)
        return;
    p = strchr(p, '=') + 1;
    tport = atoi(p);

    rtsp_take_player();
    int sport = rtp_setup(&conn->remote, cport, tport);
    if (!sport)
        return;

    player_play(&conn->stream);

    char resphdr[128]={0};
    snprintf(resphdr, sizeof(resphdr),
             "RTP/AVP/UDP;unicast;mode=record;server_port=%d;control_port=%d;timing_port=%d",
             sport, sport, sport);
    msg_add_header(resp, "Transport", resphdr);

    msg_add_header(resp, "Session", "1");

    resp->respcode = 200;
}
Ejemplo n.º 7
0
static void handle_setup(rtsp_conn_info *conn,
                         rtsp_message *req, rtsp_message *resp) {
    int cport, tport;
    char *hdr = msg_get_header(req, "Transport");
    if (!hdr)
        return;

    char *p;
    p = strstr(hdr, "control_port=");
    if (!p)
        return;
    p = strchr(p, '=') + 1;
    cport = atoi(p);

    p = strstr(hdr, "timing_port=");
    if (!p)
        return;
    p = strchr(p, '=') + 1;
    tport = atoi(p);

    rtsp_take_player();
    int sport = rtp_setup(&conn->remote, cport, tport);
    if (!sport)
        return;

    player_play(&conn->stream);

    char *resphdr = malloc(strlen(hdr) + 20);
    strcpy(resphdr, hdr);
    sprintf(resphdr + strlen(resphdr), ";server_port=%d", sport);
    msg_add_header(resp, "Transport", resphdr);

    msg_add_header(resp, "Session", "1");

    resp->respcode = 200;
}
Ejemplo n.º 8
0
static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {

    if (!config.password)
        return 0;
    if (!*nonce) {
        *nonce = make_nonce();
        goto authenticate;
    }

    char *hdr = msg_get_header(req, "Authorization");
    if (!hdr || strncmp(hdr, "Digest ", 7))
        goto authenticate;

    char *realm = strstr(hdr, "realm=\"");
    char *username = strstr(hdr, "username=\"");
    char *response = strstr(hdr, "response=\"");
    char *uri = strstr(hdr, "uri=\"");

    if (!realm || !username || !response || !uri)
        goto authenticate;

    char *quote;
    realm = strchr(realm, '"') + 1;
    if (!(quote = strchr(realm, '"')))
        goto authenticate;
    *quote = 0;
    username = strchr(username, '"') + 1;
    if (!(quote = strchr(username, '"')))
        goto authenticate;
    *quote = 0;
    response = strchr(response, '"') + 1;
    if (!(quote = strchr(response, '"')))
        goto authenticate;
    *quote = 0;
    uri = strchr(uri, '"') + 1;
    if (!(quote = strchr(uri, '"')))
        goto authenticate;
    *quote = 0;

    uint8_t digest_urp[16], digest_mu[16], digest_total[16];
    MD5_CTX ctx;
    MD5_Init(&ctx);
    MD5_Update(&ctx, username, strlen(username));
    MD5_Update(&ctx, ":", 1);
    MD5_Update(&ctx, realm, strlen(realm));
    MD5_Update(&ctx, ":", 1);
    MD5_Update(&ctx, config.password, strlen(config.password));
    MD5_Final(digest_urp, &ctx);

    MD5_Init(&ctx);
    MD5_Update(&ctx, req->method, strlen(req->method));
    MD5_Update(&ctx, ":", 1);
    MD5_Update(&ctx, uri, strlen(uri));
    MD5_Final(digest_mu, &ctx);

    int i;
    char buf[33];
    for (i=0; i<16; i++)
        sprintf(buf + 2*i, "%02X", digest_urp[i]);
    MD5_Init(&ctx);
    MD5_Update(&ctx, buf, 32);
    MD5_Update(&ctx, ":", 1);
    MD5_Update(&ctx, *nonce, strlen(*nonce));
    MD5_Update(&ctx, ":", 1);
    for (i=0; i<16; i++)
        sprintf(buf + 2*i, "%02X", digest_mu[i]);
    MD5_Update(&ctx, buf, 32);
    MD5_Final(digest_total, &ctx);

    for (i=0; i<16; i++)
        sprintf(buf + 2*i, "%02X", digest_total[i]);

    if (!strcmp(response, buf))
        return 0;
    warn("auth failed");

authenticate:
    resp->respcode = 401;
    int hdrlen = strlen(*nonce) + 40;
    char *authhdr = malloc(hdrlen);
    snprintf(authhdr, hdrlen, "Digest realm=\"taco\", nonce=\"%s\"", *nonce);
    msg_add_header(resp, "WWW-Authenticate", authhdr);
    free(authhdr);
    return 1;
}