コード例 #1
0
ファイル: mimegpg.c プロジェクト: zixia/wmail
static void checksign(struct mimestack **stack, int *iseof,
                      struct header *h,
                      FILE *fpin, FILE *fpout,
                      int argc, char **argv)
{
    char buf[BUFSIZ];
    struct header *h2;

    char signed_content[TEMPNAMEBUFSIZE];
    char signature[TEMPNAMEBUFSIZE];
    int signed_file, signature_file;
    FILE *signed_file_fp, *signature_file_fp;
    int clos_flag;
    int need_nl, check_boundary;
    struct mimestack *b=0;
    struct mime_header *mh;
    int qpdecode=0;

    signed_file=mimegpg_tempfile(signed_content);

    if (signed_file < 0 || (signed_file_fp=fdopen(signed_file, "w+")) == 0)
    {
        if (signed_file > 0)
        {
            close(signed_file);
            unlink(signed_content);
        }
        perror("open");
        exit(1);
    }
    noexec(signed_file_fp);

    find_boundary(stack, iseof, fpin, NULL, 0);
    if (*iseof)
        return;

    need_nl=0;
    check_boundary=1;

    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            continue;
        }

        if (check_boundary
                && (b=is_boundary(*stack, buf, &clos_flag)) != 0)
            break;
        if (need_nl)
            fprintf(signed_file_fp, "\r\n");

        for (p=buf; *p && *p != '\n'; p++)
            putc(*p, signed_file_fp);
        need_nl=check_boundary= *p != 0;
    }

    if (my_rewind(signed_file_fp) < 0)
    {
        perror(signed_content);
        fclose(signed_file_fp);
        unlink(signed_content);
        exit(1);
    }

    if (clos_flag)
    {
        fclose(signed_file_fp);
        unlink(signed_content);
        if (b)
            pop_mimestack_to(stack, b);
        find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }

    h=read_headers(stack, iseof, fpin, fpout, 0);

    if (!h || !(h2=find_header(h, "content-type:")))
    {
        fclose(signed_file_fp);
        unlink(signed_content);
        if (!*iseof)
            find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }

    mh=parse_mime_header(h2->header+sizeof("content-type:")-1);

    if (!mh)
    {
        perror("malloc");
        free_header(h);
        fclose(signed_file_fp);
        unlink(signed_content);
        exit(1);
    }

    if (!mh || strcasecmp(mh->header_name, "application/pgp-signature"))
    {
        if (!mh)
            free_mime_header(mh);
        free_header(h);
        fclose(signed_file_fp);
        unlink(signed_content);
        if (!*iseof)
            find_boundary(stack, iseof, fpin, fpout, 1);
        return;
    }
    free_mime_header(mh);

    /*
    ** In rare instances, the signature is qp-encoded.
    */

    if ((h2=find_header(h, "content-transfer-encoding:")) != NULL)
    {
        mh=parse_mime_header(h2->header
                             +sizeof("content-transfer-encoding:")-1);
        if (!mh)
        {
            perror("malloc");
            free_header(h);
            fclose(signed_file_fp);
            unlink(signed_content);
            exit(1);
        }

        if (strcasecmp(mh->header_name,
                       "quoted-printable") == 0)
            qpdecode=1;
        free_mime_header(mh);
    }
    free_header(h);

    signature_file=mimegpg_tempfile(signature);

    if (signature_file < 0
            || (signature_file_fp=fdopen(signature_file, "w+")) == 0)
    {
        if (signature_file > 0)
        {
            close(signature_file);
            unlink(signature);
        }
        fclose(signed_file_fp);
        unlink(signed_content);
        perror("open");
        exit(1);
    }

    while (!*iseof)
    {
        const char *p;

        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            continue;
        }

        if ((b=is_boundary(*stack, buf, &clos_flag)) != 0)
            break;

        for (p=buf; *p; p++)
        {
            int n;

            if (!qpdecode)
            {
                putc(*p, signature_file_fp);
                continue;
            }

            if (*p == '=' && p[1] == '\n')
                break;

            if (*p == '=' && p[1] && p[2])
            {
                n=nybble(p[1]) * 16 + nybble(p[2]);
                if ( (char)n )
                {
                    putc((char)n, signature_file_fp);
                    p += 2;
                }
                p += 2;
                continue;
            }
            putc(*p, signature_file_fp);

            /* If some spits out qp-lines > BUFSIZ, they deserve
            ** this crap.
            */
        }
    }

    fflush(signature_file_fp);
    if (ferror(signature_file_fp) || fclose(signature_file_fp))
    {
        unlink(signature);
        fclose(signed_file_fp);
        unlink(signed_content);
        perror("open");
        exit(1);
    }

    dochecksign(*stack, signed_file_fp, fpout, signed_content, signature,
                argc, argv);

    fclose(signed_file_fp);
    unlink(signature);
    unlink(signed_content);

    fprintf(fpout, "\n--%s--\n", b->boundary);

    while (!clos_flag)
    {
        if (fgets(buf, sizeof(buf), fpin) == NULL)
        {
            *iseof=1;
            break;
        }
        if (!(b=is_boundary(*stack, buf, &clos_flag)))
            clos_flag=0;
    }
    if (b)
        pop_mimestack_to(stack, b);

    if (iseof)
        return;
}
コード例 #2
0
ファイル: mimegpg.c プロジェクト: zixia/wmail
static void decrypt(struct mimestack **stack, int *iseof,
                    struct header *h,
                    FILE *fpin, FILE *fpout, int argc, char **argv)
{
    struct header *p, *q;
    char temp_file[TEMPNAMEBUFSIZE];
    int temp_fd;
    FILE *temp_fp;
    struct mime_header *mh;
    int flag;

    temp_fd=mimegpg_tempfile(temp_file);
    if (temp_fd < 0 || (temp_fp=fdopen(temp_fd, "w+")) == 0)
    {
        if (temp_fd >= 0)
            close(temp_fd);
        perror("open");
        exit(1);
    }

    for (p=h; p; p=p->next)
    {
        fprintf(temp_fp, "%s", p->header);
    }
    putc('\n', temp_fp);

    find_boundary(stack, iseof, fpin, temp_fp, 0);
    if (*iseof)
    {
        fclose(temp_fp);
        unlink(temp_file);
        return;
    }

    p=read_headers(stack, iseof, fpin, temp_fp, 0);

    if (*iseof)
    {
        free_header(p);
        fclose(temp_fp);
        unlink(temp_file);
        return;
    }

    q=find_header(p, "content-type:");

    flag=0;

    if (q)
    {
        mh=parse_mime_header(q->header+13);
        if (!mh)
        {
            perror("malloc");
            free_header(p);
            fclose(temp_fp);
            unlink(temp_file);
            exit(1);
        }

        if (strcasecmp(mh->header_name, "application/pgp-encrypted")
                == 0)
            flag=1;
        free_mime_header(mh);
    }

    for (q=p; q; q=q->next)
    {
        fprintf(temp_fp, "%s", q->header);
    }
    free_header(p);
    putc('\n', temp_fp);

    p=read_headers(stack, iseof, fpin, temp_fp, 0);

    if (*iseof)
    {
        free_header(p);
        fclose(temp_fp);
        unlink(temp_file);
        return;
    }

    q=find_header(p, "version:");

    if (flag)
    {
        if (!q || atoi(p->header + 8) != 1)
            flag=0;
    }
    for (q=p; q; q=q->next)
    {
        fprintf(temp_fp, "%s", q->header);
    }
    free_header(p);
    putc('\n', temp_fp);

    find_boundary(stack, iseof, fpin, temp_fp, 0);

    if (*iseof)
    {
        fclose(temp_fp);
        unlink(temp_file);
        return;
    }

    p=read_headers(stack, iseof, fpin, temp_fp, 0);

    if (*iseof)
    {
        free_header(p);
        fclose(temp_fp);
        unlink(temp_file);
        return;
    }

    q=find_header(p, "content-type:");

    if (q && flag)
    {
        flag=0;
        mh=parse_mime_header(q->header+13);
        if (!mh)
        {
            perror("malloc");
            free_header(p);
            fclose(temp_fp);
            unlink(temp_file);
            exit(1);
        }

        if (strcasecmp(mh->header_name, "application/octet-stream")
                == 0)
            flag=1;
        free_mime_header(mh);

        q=find_header(p, "content-transfer-encoding:");
        if (q && flag)
        {
            flag=0;
            mh=parse_mime_header(strchr(q->header, ':')+1);
            if (!mh)
            {
                perror("malloc");
                free_header(p);
                fclose(temp_fp);
                unlink(temp_file);
                exit(1);
            }

            if (strcasecmp(mh->header_name, "7bit") == 0 ||
                    strcasecmp(mh->header_name, "8bit") == 0)
                flag=1;
            free_mime_header(mh);
        }
    }

    for (q=p; q; q=q->next)
    {
        fprintf(temp_fp, "%s", q->header);
    }
    free_header(p);
    putc('\n', temp_fp);

    if (fflush(temp_fp) || ferror(temp_fp) || my_rewind(temp_fp) < 0)
    {
        perror(temp_file);
        fclose(temp_fp);
        unlink(temp_file);
        exit(1);
    }

    if (!flag)
    {
        int c;

        while ((c=getc(temp_fp)) != EOF)
        {
            putc(c, fpout);
        }
        fclose(temp_fp);
        unlink(temp_file);
        close_mime(stack, iseof, fpin, fpout);
        return;
    }

    fclose(temp_fp);
    if ((temp_fp=fopen(temp_file, "w+")) == NULL)
    {
        perror(temp_file);
        unlink(temp_file);
        exit(1);
    }
    noexec(temp_fp);
    dodecrypt(stack, iseof, fpin, temp_fp, argc, argv, temp_file,
              fpout);
    fclose(temp_fp);
    unlink(temp_file);
}
コード例 #3
0
ファイル: mimegpg.c プロジェクト: zixia/wmail
static int dosignencode(int dosign, int doencode, int dodecode,
                        FILE *fpin, FILE *fpout,
                        int argc, char **argv)
{
    struct mimestack *boundary_stack=0;
    int iseof=0;

    while (!iseof)
    {
        static const char ct_s[]="content-type:";
        struct header *h=read_headers(&boundary_stack, &iseof, fpin,
                                      fpout, dodecode ? 0:1),
                         *hct;

        if (iseof && !h)
            continue;	/* Artifact */

        hct=find_header(h, ct_s);

        /*
        ** If this is a multipart MIME section, we can keep on
        ** truckin'.
        **
        */

        if (hct)
        {
            struct mime_header *mh=
                parse_mime_header(hct->header+
                                  (sizeof(ct_s)-1));

            const char *bv;

            if (strcasecmp(mh->header_name, "multipart/x-mimegpg")
                    == 0)
            {
                /* Punt */

                char *buf=malloc(strlen(hct->header)+100);
                const char *p;

                if (!buf)
                {
                    free_mime_header(mh);
                    free_header(h);
                    perror("malloc");
                    exit(1);
                }
                strcpy(buf, "Content-Type: multipart/mixed");
                p=strchr(hct->header, ';');
                strcat(buf, p ? p:"");
                free(hct->header);
                hct->header=buf;

                mh=parse_mime_header(hct->header+
                                     sizeof(ct_s)-1);
            }

            if (strncasecmp(mh->header_name, "multipart/", 10)==0
                    && (bv=get_mime_attr(mh, "boundary")) != 0

                    && (doencode & ENCODE_ENCAPSULATE) == 0
               )
            {
                struct header *p;

                push_mimestack(&boundary_stack, bv);

                if (dodecode)
                {
                    if (strcasecmp(mh->header_name,
                                   "multipart/signed")==0
                            && (dodecode & DECODE_CHECKSIGN)
                            && isgpg(mh))
                    {
                        print_noncontent_headers(h,
                                                 fpout
                                                );
                        free_mime_header(mh);
                        checksign(&boundary_stack,
                                  &iseof,
                                  h, fpin, fpout,
                                  argc, argv);
                        free_header(h);
                        continue;
                    }

                    if (strcasecmp(mh->header_name,
                                   "multipart/encrypted")
                            ==0
                            && (dodecode & DECODE_UNENCRYPT)
                            && isgpg(mh))
                    {
                        print_noncontent_headers(h,
                                                 fpout
                                                );
                        free_mime_header(mh);
                        decrypt(&boundary_stack,
                                &iseof,
                                h,
                                fpin, fpout,
                                argc, argv);
                        free_header(h);
                        continue;
                    }
                }

                for (p=h; p; p=p->next)
                {
                    fprintf(fpout, "%s", p->header);
                }

                putc('\n', fpout);
                free_header(h);
                free_mime_header(mh);

                find_boundary(&boundary_stack, &iseof, fpin,
                              fpout, dodecode ? 0:1);
                continue;
            }
            free_mime_header(mh);
        }

        if (dodecode)
        {
            struct header *p;
            int is_message_rfc822=0;

            for (p=h; p; p=p->next)
            {
                fprintf(fpout, "%s", p->header);
            }
            putc('\n', fpout);

            /*
            ** If this is a message/rfc822 attachment, we can
            ** resume reading the next set of headers.
            */

            hct=find_header(h, ct_s);
            if (hct)
            {
                struct mime_header *mh=
                    parse_mime_header(hct->header+
                                      (sizeof(ct_s)-1));

                if (strcasecmp(mh->header_name,
                               "message/rfc822") == 0)
                    is_message_rfc822=1;
                free_mime_header(mh);
            }
            free_header(h);

            if (!is_message_rfc822)
                find_boundary(&boundary_stack, &iseof,
                              fpin, fpout, 0);
            continue;
        }

        if (doencode)
            dogpgencrypt(&boundary_stack, h, &iseof,
                         fpin, fpout, argc, argv, dosign);
        else
            dogpgsign(&boundary_stack, h, &iseof,
                      fpin, fpout, argc, argv);
        free_header(h);
    }

    if (ferror(fpout))
        return (1);
    return (0);
}
コード例 #4
0
ファイル: upload-file.c プロジェクト: simcuslee/seafile
/*
   Example multipart form-data request content format:

   --AaB03x
   Content-Disposition: form-data; name="submit-name"

   Larry
   --AaB03x
   Content-Disposition: form-data; name="file"; filename="file1.txt"
   Content-Type: text/plain

   ... contents of file1.txt ...
   --AaB03x--
*/
static evhtp_res
upload_read_cb (evhtp_request_t *req, evbuf_t *buf, void *arg)
{
    RecvFSM *fsm = arg;
    char *line;
    size_t len;
    gboolean no_line = FALSE;
    int res = EVHTP_RES_OK;

    if (fsm->state == RECV_ERROR)
        return EVHTP_RES_OK;

    /* Update upload progress. */
    fsm->progress->uploaded += (gint64)evbuffer_get_length(buf);

    seaf_debug ("progress: %lld/%lld\n",
                fsm->progress->uploaded, fsm->progress->size);

    evbuffer_add_buffer (fsm->line, buf);
    /* Drain the buffer so that evhtp don't copy it to another buffer
     * after this callback returns. 
     */
    evbuffer_drain (buf, evbuffer_get_length (buf));

    while (!no_line) {
        switch (fsm->state) {
        case RECV_INIT:
            line = evbuffer_readln (fsm->line, &len, EVBUFFER_EOL_CRLF_STRICT);
            if (line != NULL) {
                seaf_debug ("[upload] boundary line: %s.\n", line);
                if (!strstr (line, fsm->boundary)) {
                    seaf_warning ("[upload] no boundary found in the first line.\n");
                    free (line);
                    res = EVHTP_RES_BADREQ;
                    goto out;
                } else {
                    fsm->state = RECV_HEADERS;
                    free (line);
                }
            } else {
                no_line = TRUE;
            }
            break;
        case RECV_HEADERS:
            line = evbuffer_readln (fsm->line, &len, EVBUFFER_EOL_CRLF_STRICT);
            if (line != NULL) {
                seaf_debug ("[upload] mime header line: %s.\n", line);
                if (len == 0) {
                    /* Read an blank line, headers end. */
                    free (line);
                    if (g_strcmp0 (fsm->input_name, "file") == 0) {
                        if (open_temp_file (fsm) < 0) {
                            seaf_warning ("[upload] Failed open temp file.\n");
                            res = EVHTP_RES_SERVERR;
                            goto out;
                        }
                    }
                    seaf_debug ("[upload] Start to recv %s.\n", fsm->input_name);
                    fsm->state = RECV_CONTENT;
                } else if (parse_mime_header (line, fsm) < 0) {
                    free (line);
                    res = EVHTP_RES_BADREQ;
                    goto out;
                } else {
                    free (line);
                }
            } else {
                no_line = TRUE;
            }
            break;
        case RECV_CONTENT:
            if (g_strcmp0 (fsm->input_name, "file") == 0)
                res = recv_file_data (fsm, &no_line);
            else
                res = recv_form_field (fsm, &no_line);

            if (res != EVHTP_RES_OK)
                goto out;

            break;
        }
    }

out:
    if (res != EVHTP_RES_OK) {
        /* Don't receive any data before the connection is closed. */
        evhtp_request_pause (req);

        /* Set keepalive to 0. This will cause evhtp to close the
         * connection after sending the reply.
         */
        req->keepalive = 0;

        fsm->state = RECV_ERROR;
    }

    if (res == EVHTP_RES_BADREQ) {
        evhtp_send_reply (req, EVHTP_RES_BADREQ);
    } else if (res == EVHTP_RES_SERVERR) {
        evbuffer_add_printf (req->buffer_out, "Internal server error\n");
        evhtp_send_reply (req, EVHTP_RES_SERVERR);
    }
    return EVHTP_RES_OK;
}