コード例 #1
0
// ALWAYS generates an HTML reply
//
int handle_file_upload(FILE* in, R_RSA_PUBLIC_KEY& key) {
    char buf[256], path[MAXPATHLEN], signed_xml[1024];
    char name[256], stemp[256];
    double max_nbytes=-1;
    char xml_signature[1024];
    int retval;
    double offset=0, nbytes = -1;
    bool is_valid, btemp;

    strcpy(name, "");
    strcpy(xml_signature, "");
    bool found_data = false;
    while (fgets(buf, 256, in)) {
#if 1
        log_messages.printf(MSG_NORMAL, "got:%s\n", buf);
#endif
        if (match_tag(buf, "<file_info>")) continue;
        if (match_tag(buf, "</file_info>")) continue;
        if (match_tag(buf, "<signed_xml>")) continue;
        if (match_tag(buf, "</signed_xml>")) continue;
        if (parse_bool(buf, "generated_locally", btemp)) continue;
        if (parse_bool(buf, "upload_when_present", btemp)) continue;
        if (parse_str(buf, "<url>", stemp, sizeof(stemp))) continue;
        if (parse_str(buf, "<md5_cksum>", stemp, sizeof(stemp))) continue;
        if (match_tag(buf, "<xml_signature>")) {
            copy_element_contents(
                in, "</xml_signature>", xml_signature, sizeof(xml_signature)
            );
            continue;
        }
        if (parse_str(buf, "<name>", name, sizeof(name))) {
            strcpy(this_filename, name);
            continue;
        }
        if (parse_double(buf, "<max_nbytes>", max_nbytes)) continue;
        if (parse_double(buf, "<offset>", offset)) continue;
        if (parse_double(buf, "<nbytes>", nbytes)) continue;
        if (match_tag(buf, "<data>")) {
            found_data = true;
            break;
        }
        log_messages.printf(MSG_CRITICAL, "unrecognized: %s", buf);
    }
    if (strlen(name) == 0) {
        return return_error(ERR_PERMANENT, "Missing name");
    }
    if (!found_data) {
        return return_error(ERR_PERMANENT, "Missing <data> tag");
    }
    if (!config.ignore_upload_certificates) {
        if (strlen(xml_signature) == 0) {
            return return_error(ERR_PERMANENT, "missing signature");
        }
        if (max_nbytes < 0) {
            return return_error(ERR_PERMANENT, "missing max_nbytes");
        }
        sprintf(signed_xml,
            "<name>%s</name><max_nbytes>%.0f</max_nbytes>",
            name, max_nbytes
        );
        retval = check_string_signature(
            signed_xml, xml_signature, key, is_valid
        );
        if (retval || !is_valid) {
            log_messages.printf(MSG_CRITICAL,
                "check_string_signature() [%s] [%s] retval %d, is_valid = %d\n",
                signed_xml, xml_signature,
                retval, is_valid
            );
            log_messages.printf(MSG_NORMAL,
                "signed xml: %s\n", signed_xml
            );
            log_messages.printf(MSG_NORMAL,
                "signature: %s\n", xml_signature
            );
            return return_error(ERR_PERMANENT, "invalid signature");
        }
    }
    if (nbytes < 0) {
        return return_error(ERR_PERMANENT, "nbytes missing or negative");
    }

    // enforce limits in signed XML
    //
    if (!config.ignore_upload_certificates) {
        if (nbytes > max_nbytes) {
            sprintf(buf,
                "file size (%d KB) exceeds limit (%d KB)",
                (int)(nbytes/1024), (int)(max_nbytes/1024)
            );
            copy_socket_to_null(in);
            return return_error(ERR_PERMANENT, buf);
        }
    }

    // make sure filename is legit
    //
    if (strstr(name, "..")) {
        return return_error(ERR_PERMANENT,
            "file_upload_handler: .. found in filename: %s",
            name
        );
    }

    if (strlen(name) == 0) {
        return return_error(ERR_PERMANENT,
            "file_upload_handler: no filename; nbytes %f", nbytes
        );
    }

    retval = dir_hier_path(
        name, config.upload_dir, config.uldl_dir_fanout,
        path, true
    );
    if (retval) {
        log_messages.printf(MSG_CRITICAL,
            "Failed to find/create directory for file '%s' in '%s'\n",
            name, config.upload_dir
        );
        return return_error(ERR_TRANSIENT, "can't open file");
    }
    log_messages.printf(MSG_NORMAL,
        "Starting upload of %s from %s [offset=%.0f, nbytes=%.0f]\n",
        name,
        get_remote_addr(),
        offset, nbytes
    );
#ifndef _USING_FCGI_
    fflush(stderr);
#endif
    if (offset >= nbytes) {
        log_messages.printf(MSG_CRITICAL,
            "ERROR: offset >= nbytes!!\n"
        );
        return return_success(0);
    }
    retval = copy_socket_to_file(in, path, offset, nbytes);
    log_messages.printf(MSG_NORMAL,
        "Ended upload of %s from %s; retval %d\n",
        name,
        get_remote_addr(),
        retval
    );
#ifndef _USING_FCGI_
    fflush(stderr);
#endif
    return retval;
}
コード例 #2
0
// ALWAYS generates an HTML reply
//
int handle_file_upload(FILE* in, R_RSA_PUBLIC_KEY& key) {
    char buf[256], path[512], temp[256];
    FILE_INFO file_info;
    int retval;
    double nbytes=-1, offset=0;
    bool is_valid;

    while (fgets(buf, 256, in)) {
#if 0
        log_messages.printf(MSG_NORMAL, "got:%s\n", buf);
#endif
        if (match_tag(buf, "<file_info>")) {
            retval = file_info.parse(in);
            if (retval) {
                return return_error(ERR_PERMANENT, "FILE_INFO::parse");
            }
#if 0
            log_messages.printf(MSG_NORMAL,
                "file info:\n%s\n", file_info.signed_xml
            );
#endif
            if (!config.ignore_upload_certificates) {
                if (!file_info.signed_xml || !file_info.xml_signature) {
                    log_messages.printf(MSG_CRITICAL,
                        "file info is missing signature\n"
                    );
                    return return_error(ERR_PERMANENT, "invalid signature");
                } else {
                    retval = verify_string(
                        file_info.signed_xml, file_info.xml_signature, key, is_valid
                    );
                    if (retval || !is_valid) {
                        log_messages.printf(MSG_CRITICAL,
                            "verify_string() [%s] [%s] retval %d, is_valid = %d\n",
                            file_info.signed_xml, file_info.xml_signature,
                            retval, is_valid
                        );
                        log_messages.printf(MSG_NORMAL,
                            "signed xml: %s", file_info.signed_xml
                        );
                        log_messages.printf(MSG_NORMAL,
                            "signature: %s", file_info.xml_signature
                        );
                        return return_error(ERR_PERMANENT, "invalid signature");
                    }
                }
            }
            continue;
        }
        if (parse_double(buf, "<offset>", offset)) continue;
        if (parse_double(buf, "<nbytes>", nbytes)) continue;
        if (parse_str(buf, "<md5_cksum>", temp, sizeof(temp))) continue;
        if (match_tag(buf, "<data>")) {
            if (nbytes < 0) {
                return return_error(ERR_PERMANENT, "nbytes missing or negative");
            }

            // enforce limits in signed XML
            //
            if (!config.ignore_upload_certificates) {
                if (nbytes > file_info.max_nbytes) {
                    sprintf(buf,
                        "file size (%d KB) exceeds limit (%d KB)",
                        (int)(nbytes/1024), (int)(file_info.max_nbytes/1024)
                    );
                    copy_socket_to_null(in);
                    return return_error(ERR_PERMANENT, buf);
                }
            }

            // make sure filename is legit
            //
            if (strstr(file_info.name, "..")) {
                return return_error(ERR_PERMANENT,
                    "file_upload_handler: .. found in filename: %s",
                    file_info.name
                );
            }

            if (strlen(file_info.name) == 0) {
                return return_error(ERR_PERMANENT,
                    "file_upload_handler: no filename; nbytes %f", nbytes
                );
            }

            retval = dir_hier_path(
                file_info.name, config.upload_dir, config.uldl_dir_fanout,
                path, true
            );
            if (retval) {
                log_messages.printf(MSG_CRITICAL,
                    "Failed to find/create directory for file '%s' in '%s'\n",
                    file_info.name, config.upload_dir
                );
                return return_error(ERR_TRANSIENT, "can't open file");
            }
            log_messages.printf(MSG_NORMAL,
                "Starting upload of %s from %s [offset=%.0f, nbytes=%.0f]\n",
                file_info.name,
                get_remote_addr(),
                offset, nbytes
            );
#ifndef _USING_FCGI_
            fflush(stderr);
#endif
            if (offset >= nbytes) {
                log_messages.printf(MSG_CRITICAL,
                    "ERROR: offset >= nbytes!!\n"
                );
                return return_success(0);
            }
            retval = copy_socket_to_file(in, path, offset, nbytes);
            log_messages.printf(MSG_NORMAL,
                "Ended upload of %s from %s; retval %d\n",
                file_info.name,
                get_remote_addr(),
                retval
            );
#ifndef _USING_FCGI_
            fflush(stderr);
#endif
            return retval;
        }
        log_messages.printf(MSG_CRITICAL,
            "unrecognized: %s", buf
        );
    }
    return return_error(ERR_PERMANENT, "Missing <data> tag");
}