Esempio n. 1
0
static int autocreate_sieve(const char *userid, const char *source_script)
{
    /* XXX - this is really ugly, but too much work to tidy up right now -- Bron */
    sieve_script_t *s = NULL;
    bytecode_info_t *bc = NULL;
    char *err = NULL;
    FILE *in_stream, *out_fp;
    int out_fd, in_fd, r, k;
    int do_compile = 0;
    const char *compiled_source_script = NULL;
    const char *sievename = get_script_name(source_script);
    const char *sieve_script_dir = NULL;
    char sieve_script_name[MAX_FILENAME];
    char sieve_bcscript_name[MAX_FILENAME];
    char sieve_default[MAX_FILENAME];
    char sieve_tmpname[MAX_FILENAME];
    char sieve_bctmpname[MAX_FILENAME];
    char sieve_bclink_name[MAX_FILENAME];
    char buf[4096];
    mode_t oldmask;
    struct stat statbuf;

    /* We don't support using the homedirectory, like timsieved */
    if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) {
        syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf");
        return 1;
    }

    /* Check if sievedir is defined in imapd.conf */
    if(!config_getstring(IMAPOPT_SIEVEDIR)) {
        syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf");
        return 1;
    }

    /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */
    if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILED))) {
        syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it");
        do_compile = 1;
    }

    if (!(sieve_script_dir = user_sieve_path(userid))) {
        syslog(LOG_WARNING, "autocreate_sieve: unable to determine sieve directory for user %s", userid);
        return 1;
    }

    if(snprintf(sieve_tmpname, MAX_FILENAME, "%s/%s.script.NEW",sieve_script_dir, sievename) >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }
    if(snprintf(sieve_bctmpname, MAX_FILENAME, "%s/%s.bc.NEW",sieve_script_dir, sievename) >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }
    if(snprintf(sieve_script_name, MAX_FILENAME, "%s/%s.script",sieve_script_dir, sievename) >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }
    if(snprintf(sieve_bcscript_name, MAX_FILENAME, "%s/%s.bc",sieve_script_dir, sievename) >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }
    if(snprintf(sieve_default, MAX_FILENAME, "%s/%s",sieve_script_dir,"defaultbc") >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }
    /* XXX no directory? umm */
    if(snprintf(sieve_bclink_name, MAX_FILENAME, "%s.bc", sievename) >= MAX_FILENAME) {
        syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid);
        return 1;
    }

    /* Check if a default sieve filter alrady exists */
    if(!stat(sieve_default,&statbuf)) {
        syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists");
        return 1;
    }

    /* Open the source script. if there is a problem with that exit */
    in_stream = fopen(source_script, "r");
    if(!in_stream) {
        syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script);
        return 1;
    }

    /*
     * At this point we start the modifications of the filesystem
     */

    /* Create the directory where the sieve scripts will reside */
    r = cyrus_mkdir(sieve_bctmpname, 0755);
    if(r == -1) {
        /* If this fails we just leave */
        fclose(in_stream);
        return 1;
    }

    /*
     * We open the file that will be used as the bc file. If this file exists, overwrite it
     * since something bad has happened. We open the file here so that this error checking is
     * done before we try to open the rest of the files to start copying etc.
     */
    out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if(out_fd < 0) {
        if(errno == EEXIST) {
            syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname);
        } else if (errno == EACCES) {
            syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname);
            fclose(in_stream);
            return 1;
        } else {
            syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s: %m",sieve_bctmpname);
            fclose(in_stream);
            return 1;
        }
    }

    if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) {
        while((r = read(in_fd, buf, sizeof(buf))) > 0) {
            if((k=write(out_fd, buf,r)) < 0) {
                syslog(LOG_WARNING, "autocreate_sieve: Error writing to file %s: %m", sieve_bctmpname);
                close(out_fd);
                close(in_fd);
                fclose(in_stream);
                unlink(sieve_bctmpname);
                return 1;
           }
        }

        if(r == 0) { /* EOF */
            xclose(out_fd);
            xclose(in_fd);
        } else if (r < 0) {
            syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file %s: %m. Will try to compile it",
                           compiled_source_script);
            xclose(in_fd);
            do_compile = 1;
            if(lseek(out_fd, 0, SEEK_SET)) {
                syslog(LOG_WARNING, "autocreate_sieve: Major IO problem (lseek: %m). Aborting");
                xclose(out_fd);
                return 1;
            }
        }
        xclose(in_fd);
    } else {
        if(compiled_source_script)
              syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script);
        do_compile = 1;
    }


    /* Because we failed to open a precompiled bc sieve script, we compile one */
    if(do_compile) {
       if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) {
            if(err && *err) {
               syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err);
               free(err);
            } else
                syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script");

            unlink(sieve_bctmpname);
            fclose(in_stream);
            close(out_fd);
            return 1;
        }

        /* generate the bytecode */
        if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) {
            syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script");
            /* removing the copied script and cleaning up memory */
            unlink(sieve_bctmpname);
            sieve_script_free(&s);
            fclose(in_stream);
            close(out_fd);
            return 1;
        }

        if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) {
            syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script");
            /* removing the copied script and cleaning up memory */
            unlink(sieve_bctmpname);
            sieve_free_bytecode(&bc);
            sieve_script_free(&s);
            fclose(in_stream);
            close(out_fd);
            return 1;
        }

        /* clean up the memory */
        sieve_free_bytecode(&bc);
        sieve_script_free(&s);
    }

    xclose(out_fd);
    rewind(in_stream);

    /* Copy the initial script */
    oldmask = umask(077);
    if((out_fp = fopen(sieve_tmpname, "w")) == NULL) {
        syslog(LOG_WARNING,"autocreate_sieve: Unable to open destination sieve script %s: %m", sieve_tmpname);
        unlink(sieve_bctmpname);
        umask(oldmask);
        fclose(in_stream);
        return 1;
    }
    umask(oldmask);

    while((r = fread(buf,sizeof(char), sizeof(buf), in_stream)) > 0) {
        if( fwrite(buf,sizeof(char), r, out_fp) != (unsigned)r) {
            syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file %s: %m",sieve_tmpname);
            fclose(out_fp);
            unlink(sieve_tmpname);
            unlink(sieve_bctmpname);
            fclose(in_stream);
            return 1;
        }
    }

    if(feof(in_stream)) {
        fclose(out_fp);
        fclose(in_stream);
    } else { /* ferror */
        fclose(out_fp);
        unlink(sieve_tmpname);
        unlink(sieve_bctmpname);
        fclose(in_stream);
        return 1;
    }

    /* Renaming the necessary stuff */
    if(rename(sieve_tmpname, sieve_script_name)) {
        unlink(sieve_tmpname);
        unlink(sieve_bctmpname);
        return 1;
    }

    if(rename(sieve_bctmpname, sieve_bcscript_name)) {
        unlink(sieve_bctmpname);
        unlink(sieve_bcscript_name);
        return 1;
    }

    /* end now with the symlink */
    if(symlink(sieve_bclink_name, sieve_default)) {
        if(errno != EEXIST) {
            syslog(LOG_WARNING, "autocreate_sieve: problem making the default link (symlink: %m).");
            /* Lets delete the files */
            unlink(sieve_script_name);
            unlink(sieve_bcscript_name);
        }
    }

    /*
     * If everything has succeeded AND we have compiled the script AND we have requested
     * to generate the global script so that it is not compiled each time then we create it.
     */
    if(do_compile &&
          config_getswitch(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILE)) {

        if(!compiled_source_script) {
            syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf");
            return 0;
        }

        if(snprintf(sieve_tmpname, MAX_FILENAME, "%s.NEW", compiled_source_script) >= MAX_FILENAME)
            return 0;

        /*
         * Copy everything from the newly created bc sieve sieve script.
         */
        if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) {
            return 0;
        }

        if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
            if(errno == EEXIST) {
               /* Someone is already doing this so just bail out. */
               syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname);
                close(in_fd);
                return 0;
            } else if (errno == EACCES) {
                syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname);
                close(in_fd);
                return 0;
            } else {
                syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s: %m",sieve_tmpname);
                close(in_fd);
                return 0;
            }
        }

        while((r = read(in_fd, buf, sizeof(buf))) > 0) {
            if((k = write(out_fd,buf,r)) < 0) {
                syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s: %m", sieve_tmpname);
                close(out_fd);
                close(in_fd);
                unlink(sieve_tmpname);
                return 0;
           }
        }

        if(r == 0 ) { /*EOF */
            xclose(out_fd);
            xclose(in_fd);
        } else if (r < 0) {
                syslog(LOG_WARNING, "autocreate_sieve: Error reading file: %s: %m", sieve_bcscript_name);
                xclose(out_fd);
                xclose(in_fd);
                unlink(sieve_tmpname);
                return 0;
        }

        /* Rename the temporary created sieve script to its final name. */
        if(rename(sieve_tmpname, compiled_source_script)) {
            if(errno != EEXIST) {
               unlink(sieve_tmpname);
               unlink(compiled_source_script);
        }
            return 0;
        }

        syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script);
    }

    return 0;
}
Esempio n. 2
0
static int
_add_script(lua_State *L)
{
    int si;
    char *string;

    if(! lua_istable(L, 1) ) {
        luaL_error(L, "Table needed to add script");
    }

    si = _get_new_script();

    if(si < 0) {
        /* Just bail for now */
        return 0;
    }

    lua_getfield(L, 1, "enable");
    if( lua_isnil(L, -1)) {
        scripts[si].enable = 1;
    } else {
        scripts[si].enable = lua_toboolean(L, -1);
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "trigger");
    if(lua_istable(L, -1)) {
        _set_trigger(L, &scripts[si]);
    } else {
        scripts[si].trigger = 0;
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "name");
    string = (char *)lua_tostring(L, -1);
    fprintf(stderr, "We got a script name of %s\n", string);
    if(string) {
        /* check for duplicate name */
        if(get_script_name(string)) {
            scriptcount--; /* This effectively deletes the script */
            luaL_error(L, "duplicate script name %s", string);
        }
        scripts[si].name = strdup(string);
    } else {
        luaL_error(L, "name is required for a script");
        scripts[si].name = NULL;
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "filename");
    string = (char *)lua_tostring(L, -1);
    if(string) {
        scripts[si].filename = strdup(string);
    } else {
        scripts[si].filename = NULL;
        scripts[si].enable = 0;
    }
    lua_pop(L, 1);

    lua_getfield(L, 1, "rate");
    scripts[si].rate = lua_tointeger(L, -1);
    if(scripts[si].rate <= 0) {
        scripts[si].rate = DEFAULT_RATE;
    }
    lua_pop(L, 1);

    return 0;
}
static int SavePackageDescriptionToDebugDump(const char *dump_dir_name, const char *chroot)
{
    struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        return 1;

    char *type = dd_load_text(dd, FILENAME_TYPE);
    if (!strcmp(type, "Kerneloops"))
    {
        dd_save_text(dd, FILENAME_PACKAGE, "kernel");
        dd_save_text(dd, FILENAME_COMPONENT, "kernel");
        dd_close(dd);
        free(type);
        return 0;
    }
    free(type);

    char *cmdline = NULL;
    char *executable = NULL;
    char *rootdir = NULL;
    char *package_short_name = NULL;
    struct pkg_envra *pkg_name = NULL;
    char *component = NULL;
    int error = 1;
    /* note: "goto ret" statements below free all the above variables,
     * but they don't dd_close(dd) */

    cmdline = dd_load_text_ext(dd, FILENAME_CMDLINE, DD_FAIL_QUIETLY_ENOENT);
    executable = dd_load_text(dd, FILENAME_EXECUTABLE);
    if (chroot == NULL)
        chroot = rootdir = dd_load_text_ext(dd, FILENAME_ROOTDIR,
                               DD_FAIL_QUIETLY_ENOENT | DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);

    /* Close dd while we query package database. It can take some time,
     * don't want to keep dd locked longer than necessary */
    dd_close(dd);

    if (is_path_blacklisted(executable))
    {
        log("Blacklisted executable '%s'", executable);
        goto ret; /* return 1 (failure) */
    }

    pkg_name = rpm_get_package_nvr(executable, chroot);
    if (!pkg_name)
    {
        if (settings_bProcessUnpackaged)
        {
            log_info("Crash in unpackaged executable '%s', "
                      "proceeding without packaging information", executable);
            goto ret0; /* no error */
        }
        log("Executable '%s' doesn't belong to any package"
		" and ProcessUnpackaged is set to 'no'",
		executable
        );
        goto ret; /* return 1 (failure) */
    }

    /* Check well-known interpreter names */
    const char *basename = strrchr(executable, '/');
    if (basename)
        basename++;
    else
        basename = executable;

    /* if basename is known interpreter, we want to blame the running script
     * not the interpreter
     */
    if (g_list_find_custom(settings_Interpreters, basename, (GCompareFunc)g_strcmp0))
    {
        struct pkg_envra *script_pkg = get_script_name(cmdline, &executable, chroot);
        /* executable may have changed, check it again */
        if (is_path_blacklisted(executable))
        {
            log("Blacklisted executable '%s'", executable);
            goto ret; /* return 1 (failure) */
        }
        if (!script_pkg)
        {
            /* Script name is not absolute, or it doesn't
             * belong to any installed package.
             */
            if (!settings_bProcessUnpackaged)
            {
                log("Interpreter crashed, but no packaged script detected: '%s'", cmdline);
                goto ret; /* return 1 (failure) */
            }

            /* Unpackaged script, but the settings says we want to keep it.
             * BZ plugin wont allow to report this anyway, because component
             * is missing, so there is no reason to mark it as not_reportable.
             * Someone might want to use abrt to report it using ftp.
             */
            goto ret0;
        }

        free_pkg_envra(pkg_name);
        pkg_name = script_pkg;
    }

    package_short_name = xasprintf("%s", pkg_name->p_name);
    log_info("Package:'%s' short:'%s'", pkg_name->p_nvr, package_short_name);


    if (g_list_find_custom(settings_setBlackListedPkgs, package_short_name, (GCompareFunc)g_strcmp0))
    {
        log("Blacklisted package '%s'", package_short_name);
        goto ret; /* return 1 (failure) */
    }

    if (settings_bOpenGPGCheck)
    {
        if (!rpm_chk_fingerprint(package_short_name))
        {
            log("Package '%s' isn't signed with proper key", package_short_name);
            goto ret; /* return 1 (failure) */
        }
        /* We used to also check the integrity of the executable here:
         *  if (!CheckHash(package_short_name.c_str(), executable)) BOOM();
         * Checking the MD5 sum requires to run prelink to "un-prelink" the
         * binaries - this is considered potential security risk so we don't
         * do it now, until we find some non-intrusive way.
         */
    }

    component = rpm_get_component(executable, chroot);

    dd = dd_opendir(dump_dir_name, /*flags:*/ 0);
    if (!dd)
        goto ret; /* return 1 (failure) */

    if (pkg_name)
    {
        dd_save_text(dd, FILENAME_PACKAGE, pkg_name->p_nvr);
        dd_save_text(dd, FILENAME_PKG_EPOCH, pkg_name->p_epoch);
        dd_save_text(dd, FILENAME_PKG_NAME, pkg_name->p_name);
        dd_save_text(dd, FILENAME_PKG_VERSION, pkg_name->p_version);
        dd_save_text(dd, FILENAME_PKG_RELEASE, pkg_name->p_release);
        dd_save_text(dd, FILENAME_PKG_ARCH, pkg_name->p_arch);
    }

    if (component)
        dd_save_text(dd, FILENAME_COMPONENT, component);

    dd_close(dd);

 ret0:
    error = 0;
 ret:
    free(cmdline);
    free(executable);
    free(rootdir);
    free(package_short_name);
    free_pkg_envra(pkg_name);
    free(component);

    return error;
}