Esempio n. 1
0
static void test_sparse_files_8(void)
{
    Log(LOG_LEVEL_VERBOSE,
        "Special Case: File ending with few (DEV_BSIZE-1) zeroes,"
        " at block size barrier; so the last bytes written are a hole and are seek()ed,"
        " but the output file can't be sparse since the hole isn't block-sized");

    char *buf = xmalloc(TESTFILE_SIZE + DEV_BSIZE - 1);

    FillBufferWithGarbage(buf, TESTFILE_SIZE);
    memset(&buf[TESTFILE_SIZE], 0, DEV_BSIZE - 1);

    WriteBufferToFile(srcfile, buf, TESTFILE_SIZE + DEV_BSIZE - 1);

    /* ACTUAL TEST */
    bool ret = CopyRegularFileDisk(srcfile, dstfile);
    assert_true(ret);

    if (SPARSE_SUPPORT_OK)
    {
        bool is_sparse = FileIsSparse(dstfile);
        assert_false(is_sparse);
    }

    bool data_ok = CompareFileToBuffer(dstfile, buf, TESTFILE_SIZE + DEV_BSIZE - 1);
    assert_true(data_ok);

    free(buf);
    test_has_run[8] = true;
    success     [8] = true;
}
Esempio n. 2
0
static void test_sparse_files_7(void)
{
    Log(LOG_LEVEL_VERBOSE,
        "File ending with many zeroes, the output file must be sparse");

    char *buf = xmalloc(TESTFILE_SIZE);

    FillBufferWithGarbage(buf, TESTFILE_SIZE);
    memset(&buf[TESTFILE_SIZE - LONG_REGION], 0, LONG_REGION);

    WriteBufferToFile(srcfile, buf, TESTFILE_SIZE);

    /* ACTUAL TEST */
    bool ret = CopyRegularFileDisk(srcfile, dstfile);
    assert_true(ret);

    if (SPARSE_SUPPORT_OK)
    {
        bool is_sparse = FileIsSparse(dstfile);
        assert_true(is_sparse);
    }

    bool data_ok = CompareFileToBuffer(dstfile, buf, TESTFILE_SIZE);
    assert_true(data_ok);

    free(buf);
    test_has_run[7] = true;
    success     [7] = true;
}
Esempio n. 3
0
static void test_sparse_files_1(void)
{
    Log(LOG_LEVEL_VERBOSE,
        "No zeros in the file, the output file must be non-sparse");

    char *buf = xmalloc(TESTFILE_SIZE);

    FillBufferWithGarbage(buf, TESTFILE_SIZE);

    WriteBufferToFile(srcfile, buf, TESTFILE_SIZE);

    /* ACTUAL TEST */
    bool ret = CopyRegularFileDisk(srcfile, dstfile);
    assert_true(ret);

    if (SPARSE_SUPPORT_OK)
    {
        bool is_sparse = FileIsSparse(dstfile);
        assert_false(is_sparse);
    }

    bool data_ok = CompareFileToBuffer(dstfile, buf, TESTFILE_SIZE);
    assert_true(data_ok);

    free(buf);
    test_has_run[1] = true;
    success     [1] = true;
}
Esempio n. 4
0
int ArchiveToRepository(const char *file, Attributes attr, Promise *pp, const ReportContext *report_context)
 /* Returns true if the file was backup up and false if not */
{
    char destination[CF_BUFSIZE];
    struct stat sb, dsb;

    if (!GetRepositoryPath(file, attr, destination))
    {
        return false;
    }

    if (attr.copy.backup == cfa_nobackup)
    {
        return true;
    }

    if (IsItemIn(VREPOSLIST, file))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "",
              "The file %s has already been moved to the repository once. Multiple update will cause loss of backup.",
              file);
        return true;
    }

    ThreadLock(cft_getaddr);
    PrependItemList(&VREPOSLIST, file);
    ThreadUnlock(cft_getaddr);

    CfDebug("Repository(%s)\n", file);
    
    JoinPath(destination, CanonifyName(file));

    if (!MakeParentDirectory(destination, attr.move_obstructions, report_context))
    {
    }

    if (cfstat(file, &sb) == -1)
    {
        CfDebug("File %s promised to archive to the repository but it disappeared!\n", file);
        return true;
    }

    cfstat(destination, &dsb);

    CheckForFileHoles(&sb, pp);

    if (pp && CopyRegularFileDisk(file, destination, pp->makeholes))
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Moved %s to repository location %s\n", file, destination);
        return true;
    }
    else
    {
        CfOut(OUTPUT_LEVEL_INFORM, "", "Failed to move %s to repository location %s\n", file, destination);
        return false;
    }
}
Esempio n. 5
0
int ArchiveToRepository(const char *file, Attributes attr)
 /* Returns true if the file was backup up and false if not */
{
    char destination[CF_BUFSIZE];
    struct stat sb, dsb;

    if (!GetRepositoryPath(file, attr, destination))
    {
        return false;
    }

    if (attr.copy.backup == BACKUP_OPTION_NO_BACKUP)
    {
        return true;
    }

    if (IsItemIn(VREPOSLIST, file))
    {
        Log(LOG_LEVEL_INFO,
            "The file '%s' has already been moved to the repository once. Multiple update will cause loss of backup.",
              file);
        return true;
    }

    ThreadLock(cft_getaddr);
    PrependItemList(&VREPOSLIST, file);
    ThreadUnlock(cft_getaddr);
    
    JoinPath(destination, CanonifyName(file));

    if (!MakeParentDirectory(destination, attr.move_obstructions))
    {
    }

    if (stat(file, &sb) == -1)
    {
        Log(LOG_LEVEL_DEBUG, "File '%s' promised to archive to the repository but it disappeared!", file);
        return true;
    }

    stat(destination, &dsb);

    if (CopyRegularFileDisk(file, destination))
    {
        Log(LOG_LEVEL_INFO, "Moved '%s' to repository location '%s'", file, destination);
        return true;
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Failed to move '%s' to repository location '%s'", file, destination);
        return false;
    }
}
Esempio n. 6
0
int TrustKey(const char* pubkey)
{
    char *digeststr = GetPubkeyDigest(pubkey);
    char outfilename[CF_BUFSIZE];
    bool ok;

    if (NULL == digeststr)
        return 1; /* ERROR exitcode */

    snprintf(outfilename, CF_BUFSIZE, "%s/ppkeys/root-%s.pub", CFWORKDIR, digeststr);
    free(digeststr);

    ok = CopyRegularFileDisk(pubkey, outfilename);

    return (ok? 0 : 1);
}
Esempio n. 7
0
/**
 * @brief removes all traces of entry 'input' from lastseen and filesystem
 *
 * @param[in] key digest (SHA/MD5 format) or free host name string
 * @param[in] must_be_coherent. false : delete if lastseen is incoherent, 
 *                              true :  don't if lastseen is incoherent
 * @retval 0 if entry was deleted, >0 otherwise
 */
int RemoveKeys(const char *input, bool must_be_coherent)
{
    int res = 0;
    char equivalent[CF_BUFSIZE];
    equivalent[0] = '\0';

    res = RemoveKeysFromLastSeen(input, must_be_coherent, equivalent);
    if (res!=0)
    {
        return res;
    }

    Log(LOG_LEVEL_INFO, "Removed corresponding entries from lastseen database.");

    int removed_input      = RemovePublicKey(input);
    int removed_equivalent = RemovePublicKey(equivalent);

    if ((removed_input == -1) || (removed_equivalent == -1))
    {
        Log(LOG_LEVEL_ERR, "Unable to remove keys for the entry %s", input);
        return 255;
    }
    else if (removed_input + removed_equivalent == 0)
    {
        Log(LOG_LEVEL_ERR, "No key file(s) for entry %s were found on the filesytem", input);
        return 1;
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Removed %d corresponding key file(s) from filesystem.",
              removed_input + removed_equivalent);
        return 0;
    }

    return -1;
}

void KeepKeyPromises(const char *public_key_file, const char *private_key_file)
{
    unsigned long err;
#ifdef OPENSSL_NO_DEPRECATED
    RSA *pair = RSA_new();
    BIGNUM *rsa_bignum = BN_new();
#else
    RSA *pair;
#endif
    FILE *fp;
    struct stat statbuf;
    int fd;
    static char *passphrase = "Cfengine passphrase";
    const EVP_CIPHER *cipher;
    char vbuff[CF_BUFSIZE];

    cipher = EVP_des_ede3_cbc();

    if (stat(public_key_file, &statbuf) != -1)
    {
        printf("A key file already exists at %s\n", public_key_file);
        return;
    }

    if (stat(private_key_file, &statbuf) != -1)
    {
        printf("A key file already exists at %s\n", private_key_file);
        return;
    }

    printf("Making a key pair for cfengine, please wait, this could take a minute...\n");

#ifdef OPENSSL_NO_DEPRECATED
    BN_set_word(rsa_bignum, 35);

    if (!RSA_generate_key_ex(pair, 2048, rsa_bignum, NULL))
#else
    pair = RSA_generate_key(2048, 35, NULL, NULL);

    if (pair == NULL)
#endif
    {
        err = ERR_get_error();
        Log(LOG_LEVEL_ERR, "Unable to generate key '%s'", ERR_reason_error_string(err));
        return;
    }

    fd = open(private_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (fd < 0)
    {
        Log(LOG_LEVEL_ERR, "Open '%s' failed. (open: %s)", private_key_file, GetErrorStr());
        return;
    }

    if ((fp = fdopen(fd, "w")) == NULL)
    {
        Log(LOG_LEVEL_ERR, "Couldn't open private key '%s'. (fdopen: %s)", private_key_file, GetErrorStr());
        close(fd);
        return;
    }

    Log(LOG_LEVEL_VERBOSE, "Writing private key to '%s'", private_key_file);

    if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL))
    {
        err = ERR_get_error();
        Log(LOG_LEVEL_ERR, "Couldn't write private key. (PEM_write_RSAPrivateKey: %s)", ERR_reason_error_string(err));
        return;
    }

    fclose(fp);

    fd = open(public_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (fd < 0)
    {
        Log(LOG_LEVEL_ERR, "Unable to open public key '%s'. (open: %s)",
            public_key_file, GetErrorStr());
        return;
    }

    if ((fp = fdopen(fd, "w")) == NULL)
    {
        Log(LOG_LEVEL_ERR, "Open '%s' failed. (fdopen: %s)", public_key_file, GetErrorStr());
        close(fd);
        return;
    }

    Log(LOG_LEVEL_VERBOSE, "Writing public key to file '%s'", public_key_file);

    if (!PEM_write_RSAPublicKey(fp, pair))
    {
        err = ERR_get_error();
        Log(LOG_LEVEL_ERR, "Unable to write public key. (PEM_write_RSAPublicKey: %s)", ERR_reason_error_string(err));
        return;
    }

    fclose(fp);

    snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR);
    RAND_write_file(vbuff);
    chmod(vbuff, 0644);
}


#ifndef HAVE_NOVA
bool LicenseInstall(ARG_UNUSED char *path_source)
{
    Log(LOG_LEVEL_ERR, "License installation only applies to CFEngine Enterprise");

    return false;
}

#else  /* HAVE_NOVA */
bool LicenseInstall(char *path_source)
{
    struct stat sb;

    if(stat(path_source, &sb) == -1)
    {
        Log(LOG_LEVEL_ERR, "Can not stat input license file '%s'. (stat: %s)", path_source, GetErrorStr());
        return false;
    }

    char path_destination[MAX_FILENAME];
    snprintf(path_destination, sizeof(path_destination), "%s/inputs/license.dat", CFWORKDIR);
    MapName(path_destination);

    if(stat(path_destination, &sb) == 0)
    {
        Log(LOG_LEVEL_ERR, "A license file is already installed in '%s' -- please move it out of the way and try again", path_destination);
        return false;
    }

    char path_public_key[MAX_FILENAME];

    if(!LicensePublicKeyPath(path_public_key, path_source))
    {
        Log(LOG_LEVEL_ERR, "Could not find path to public key -- license parse error?");
    }

    if(stat(path_public_key, &sb) != 0)
    {
        Log(LOG_LEVEL_ERR, "The licensed public key is not installed -- please copy it to '%s' and try again", path_public_key);
        return false;
    }


    bool success = CopyRegularFileDisk(path_source, path_destination);

    if(success)
    {
        Log(LOG_LEVEL_INFO, "Installed license at '%s'", path_destination);
    }
    else
    {
        Log(LOG_LEVEL_ERR, "Failed copying license from '%s' to '%s'", path_source, path_destination);
    }

    return success;
}
Esempio n. 8
0
bool CopyRegularFileDiskReport(char *source, char *destination, Attributes attr, Promise *pp)
// TODO: return error codes in CopyRegularFileDisk and print them to cfPS here
{
    bool make_holes = false;

    if(pp && pp->makeholes)
    {
        make_holes = true;
    }

    bool result = CopyRegularFileDisk(source, destination, make_holes);

    if(!result)
    {
        cfPS(cf_inform, CF_FAIL, "", pp, attr, "Failed copying file %s to %s", source, destination);
    }

    return result;
}
Esempio n. 9
0
static bool ChangePasswordHashUsingLckpwdf(const char *puser, const char *password)
{
    bool result = false;

    struct stat statbuf;
    const char *passwd_file = "/etc/shadow";
    if (stat(passwd_file, &statbuf) == -1)
    {
        passwd_file = "/etc/passwd";
    }

    Log(LOG_LEVEL_VERBOSE, "Changing password hash for user '%s' by editing '%s'.", puser, passwd_file);

    if (lckpwdf() != 0)
    {
        Log(LOG_LEVEL_ERR, "Not able to obtain lock on password database.");
        return false;
    }

    char backup_file[strlen(passwd_file) + strlen(".cf-backup") + 1];
    xsnprintf(backup_file, sizeof(backup_file), "%s.cf-backup", passwd_file);
    unlink(backup_file);

    char edit_file[strlen(passwd_file) + strlen(".cf-edit") + 1];
    xsnprintf(edit_file, sizeof(edit_file), "%s.cf-edit", passwd_file);
    unlink(edit_file);

    if (!CopyRegularFileDisk(passwd_file, backup_file))
    {
        Log(LOG_LEVEL_ERR, "Could not back up existing password database '%s' to '%s'.", passwd_file, backup_file);
        goto unlock_passwd;
    }

    FILE *passwd_fd = fopen(passwd_file, "r");
    if (!passwd_fd)
    {
        Log(LOG_LEVEL_ERR, "Could not open password database '%s'. (fopen: '%s')", passwd_file, GetErrorStr());
        goto unlock_passwd;
    }
    int edit_fd_int = open(edit_file, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR);
    if (edit_fd_int < 0)
    {
        if (errno == EEXIST)
        {
            Log(LOG_LEVEL_CRIT, "Temporary file already existed when trying to open '%s'. (open: '%s') "
                "This should NEVER happen and could mean that someone is trying to break into your system!!",
                edit_file, GetErrorStr());
        }
        else
        {
            Log(LOG_LEVEL_ERR, "Could not open password database temporary file '%s'. (open: '%s')", edit_file, GetErrorStr());
        }
        goto close_passwd_fd;
    }
    FILE *edit_fd = fdopen(edit_fd_int, "w");
    if (!edit_fd)
    {
        Log(LOG_LEVEL_ERR, "Could not open password database temporary file '%s'. (fopen: '%s')", edit_file, GetErrorStr());
        close(edit_fd_int);
        goto close_passwd_fd;
    }

    while (true)
    {
        size_t line_size = 0;
        char *line = NULL;

        int read_result = CfReadLine(&line, &line_size, passwd_fd);
        if (read_result < 0)
        {
            if (!feof(passwd_fd))
            {
                Log(LOG_LEVEL_ERR, "Error while reading password database: %s", GetErrorStr());
                free(line);
                goto close_both;
            }
            else
            {
                break;
            }
        }

        // Editing the password database is risky business, so do as little parsing as possible.
        // Just enough to get the hash in there.
        char *field_start = NULL;
        char *field_end = NULL;
        field_start = strchr(line, ':');
        if (field_start)
        {
            field_end = strchr(field_start + 1, ':');
        }
        if (!field_start || !field_end)
        {
            Log(LOG_LEVEL_ERR, "Unexpected format found in password database while editing user '%s'. Not updating.",
                puser);
            free(line);
            goto close_both;
        }

        // Worst case length: Existing password is empty plus one '\n' and one '\0'.
        char new_line[strlen(line) + strlen(password) + 2];
        *field_start = '\0';
        *field_end = '\0';
        if (strcmp(line, puser) == 0)
        {
            xsnprintf(new_line, sizeof(new_line), "%s:%s:%s\n",
                     line, password, field_end + 1);
        }
        else
        {
            xsnprintf(new_line, sizeof(new_line), "%s:%s:%s\n",
                     line, field_start + 1, field_end + 1);
        }

        free(line);

        size_t new_line_size = strlen(new_line);
        size_t written_so_far = 0;
        while (written_so_far < new_line_size)
        {
            clearerr(edit_fd);
            size_t written = fwrite(new_line, 1, new_line_size, edit_fd);
            if (written == 0)
            {
                const char *err_str;
                if (ferror(edit_fd))
                {
                    err_str = GetErrorStr();
                }
                else
                {
                    err_str = "Unknown error";
                }
                Log(LOG_LEVEL_ERR, "Error while writing to file '%s'. (fwrite: '%s')", edit_file, err_str);
                goto close_both;
            }
            written_so_far += written;
        }
    }

    fclose(edit_fd);
    fclose(passwd_fd);

    if (!CopyFilePermissionsDisk(passwd_file, edit_file))
    {
        Log(LOG_LEVEL_ERR, "Could not copy permissions from '%s' to '%s'", passwd_file, edit_file);
        goto unlock_passwd;
    }

    if (rename(edit_file, passwd_file) < 0)
    {
        Log(LOG_LEVEL_ERR, "Could not replace '%s' with edited password database '%s'. (rename: '%s')",
            passwd_file, edit_file, GetErrorStr());
        goto unlock_passwd;
    }

    result = true;

    goto unlock_passwd;

close_both:
    fclose(edit_fd);
    unlink(edit_file);
close_passwd_fd:
    fclose(passwd_fd);
unlock_passwd:
    ulckpwdf();

    return result;
}
int ArchiveToRepository(char *file,struct Attributes attr,struct Promise *pp)

 /* Returns true if the file was backup up and false if not */

{ char destination[CF_BUFSIZE];
  char localrepository[CF_BUFSIZE]; 
  char node[CF_BUFSIZE];
  struct stat sb, dsb;
  char *sp;

if (attr.repository == NULL && VREPOSITORY == NULL)
   {
   return false;
   }

if (attr.repository != NULL)
   {
   strncpy(localrepository,attr.repository,CF_BUFSIZE);
   }
else if (VREPOSITORY != NULL)
   {
   strncpy(localrepository,VREPOSITORY,CF_BUFSIZE);
   }

if (attr.copy.backup == cfa_nobackup)
   {
   return true;
   }

if (IsItemIn(VREPOSLIST,file))
   {
   CfOut(cf_inform,"","The file %s has already been moved to the repository once. Multiple update will cause loss of backup.",file);
   return true;
   }

ThreadLock(cft_getaddr);
PrependItemList(&VREPOSLIST,file);
ThreadUnlock(cft_getaddr);

Debug("Repository(%s)\n",file);

strcpy (node,file);

destination[0] = '\0';

for (sp = node; *sp != '\0'; sp++)
   {
   if (*sp == FILE_SEPARATOR)
      {
      *sp = REPOSCHAR;
      }
   }

strncpy(destination,localrepository,CF_BUFSIZE-2);

if (!JoinPath(destination,node))
   {
   CfOut(cf_error,"","Internal limit: Buffer ran out of space for long filename\n");
   return false;
   }

if (!MakeParentDirectory(destination,attr.move_obstructions))
   {
   }

if (cfstat(file,&sb) == -1)
   {
   Debug("File %s promised to archive to the repository but it disappeared!\n",file);
   return true;
   }

cfstat(destination,&dsb);

attr.copy.servers = NULL;
attr.copy.backup = cfa_repos_store; // cfa_nobackup;
attr.copy.stealth = false;
attr.copy.verify = false;
attr.copy.preserve = false;

CheckForFileHoles(&sb,pp);

if (CopyRegularFileDisk(file,destination,attr,pp))
   {
   CfOut(cf_inform,"","Moved %s to repository location %s\n",file,destination);
   return true;
   }
else
   {
   CfOut(cf_inform,"","Failed to move %s to repository location %s\n",file,destination);
   return false;
   }
}
Esempio n. 11
0
void RotateFiles(char *name, int number)
{
    int i, fd;
    struct stat statbuf;
    char from[CF_BUFSIZE], to[CF_BUFSIZE];

    if (IsItemIn(ROTATED, name))
    {
        return;
    }

    PrependItem(&ROTATED, name, NULL);

    if (stat(name, &statbuf) == -1)
    {
        Log(LOG_LEVEL_VERBOSE, "No access to file %s", name);
        return;
    }

    for (i = number - 1; i > 0; i--)
    {
        snprintf(from, CF_BUFSIZE, "%s.%d", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.gz", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.gz", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.Z", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.Z", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.bz", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.bz", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }

        snprintf(from, CF_BUFSIZE, "%s.%d.bz2", name, i);
        snprintf(to, CF_BUFSIZE, "%s.%d.bz2", name, i + 1);

        if (rename(from, to) == -1)
        {
            Log(LOG_LEVEL_DEBUG, "Rename failed in RotateFiles '%s' -> '%s'", name, from);
        }
    }

    snprintf(to, CF_BUFSIZE, "%s.1", name);

    if (CopyRegularFileDisk(name, to) == false)
    {
        Log(LOG_LEVEL_DEBUG, "Copy failed in RotateFiles '%s' -> '%s'", name, to);
        return;
    }

    safe_chmod(to, statbuf.st_mode);
    if (safe_chown(to, statbuf.st_uid, statbuf.st_gid))
    {
        UnexpectedError("Failed to chown %s", to);
    }
    safe_chmod(name, 0600);       /* File must be writable to empty .. */

    if ((fd = safe_creat(name, statbuf.st_mode)) == -1)
    {
        Log(LOG_LEVEL_ERR, "Failed to create new '%s' in disable(rotate). (creat: %s)",
            name, GetErrorStr());
    }
    else
    {
        if (safe_chown(name, statbuf.st_uid, statbuf.st_gid))  /* NT doesn't have fchown */
        {
            UnexpectedError("Failed to chown '%s'", name);
        }
        fchmod(fd, statbuf.st_mode);
        close(fd);
    }
}