Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
#include <termios.h>
#endif

#ifdef HAVE_NBCOMPAT_H
#include <nbcompat/sha2.h>
#else
#include <sha2.h>
#endif

static int warn_count = 0, err_count = 0;
static uint8_t said = 0;
FILE *err_fp = NULL;
Expand Down Expand Up @@ -82,6 +88,8 @@ pkg_download(Plisthead *installhead)
(void) umask(DEF_UMASK);

if (strncmp(p->ipkg->pkgurl, "file:///", 8) == 0) {
char sha256[SHA256_DIGEST_STRING_LENGTH];

/*
* If this package repository URL is file:// we can
* just symlink rather than copying. We do not support
Expand All @@ -99,6 +107,13 @@ pkg_download(Plisthead *installhead)
continue;
}

if (p->ipkg->rpkg->sha256) {
if (SHA256_File(pkgurl, sha256) == NULL ||
strcmp(sha256, p->ipkg->rpkg->sha256) != 0)
errx(EXIT_FAILURE, "Hash mismatch %s",
p->ipkg->pkgfs);
}

if (symlink(pkgurl, p->ipkg->pkgfs) < 0) {
errx(EXIT_FAILURE,
"Failed to create symlink %s",
Expand All @@ -116,7 +131,8 @@ pkg_download(Plisthead *installhead)
err(EXIT_FAILURE, MSG_ERR_OPEN, p->ipkg->pkgfs);

p->ipkg->file_size =
download_pkg(p->ipkg->pkgurl, fp, i++, count);
download_pkg(p->ipkg->pkgurl, fp, i++, count,
p->ipkg->rpkg->sha256);

if (p->ipkg->file_size == -1) {
(void) fclose(fp);
Expand Down Expand Up @@ -613,6 +629,7 @@ pkgin_install(char **pkgargs, int do_inst, int upgrade)
char **corepkgs;
char pkgrepo[BUFSIZ], query[BUFSIZ];
char h_psize[H_BUF], h_fsize[H_BUF], h_free[H_BUF];
char sha256[SHA256_DIGEST_STRING_LENGTH];
struct stat st;

if (is_empty_remote_pkglist()) {
Expand Down Expand Up @@ -720,12 +737,16 @@ pkgin_install(char **pkgargs, int do_inst, int upgrade)

/*
* If the binary package has not already been downloaded, or
* its size does not match pkg_summary, then mark it to be
* its size/hash do not match pkg_summary, then mark it to be
* downloaded.
*/
if (stat(p->pkgfs, &st) < 0 || st.st_size != p->rpkg->file_size)
p->download = 1;
else {
else if (p->rpkg->sha256 != NULL &&
SHA256_File(p->pkgfs, sha256) != NULL &&
strcmp(p->rpkg->sha256, sha256) == 0) {
/* exact match, no further check needed */
} else {
/*
* If the cached package has the correct size, we must
* verify that the BUILD_DATE has not changed, in case
Expand Down
25 changes: 24 additions & 1 deletion download.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
#include "pkgin.h"
#include "external/progressmeter.h"

#ifdef HAVE_NBCOMPAT_H
#include <nbcompat/sha2.h>
#else
#include <sha2.h>
#endif

extern char fetchflags[3];

/*
Expand Down Expand Up @@ -159,7 +165,8 @@ sum_close(struct archive *a, void *data)
* Download a package to the local cache.
*/
off_t
download_pkg(char *pkg_url, FILE *fp, int cur, int total)
download_pkg(char *pkg_url, FILE *fp, int cur, int total,
const char *sha256_expected)
{
struct url_stat st;
size_t size, wrote;
Expand All @@ -168,6 +175,8 @@ download_pkg(char *pkg_url, FILE *fp, int cur, int total)
struct url *url;
fetchIO *f = NULL;
char buf[4096];
SHA256_CTX sha256;
char sha256_actual[SHA256_DIGEST_STRING_LENGTH];
char *pkg, *ptr, *msg = NULL;

if ((url = fetchParseURL(pkg_url)) == NULL)
Expand All @@ -194,6 +203,9 @@ download_pkg(char *pkg_url, FILE *fp, int cur, int total)
start_progress_meter(msg, st.size, &statsize);
}

if (sha256_expected)
SHA256_Init(&sha256);

while (written < st.size) {
if ((fetched = fetchIO_read(f, buf, sizeof(buf))) == 0)
break;
Expand All @@ -208,6 +220,8 @@ download_pkg(char *pkg_url, FILE *fp, int cur, int total)
statsize += fetched;
size = (size_t)fetched;

if (sha256_expected)
SHA256_Update(&sha256, (const void *)buf, size);
for (ptr = buf; size > 0; ptr += wrote, size -= wrote) {
if ((wrote = fwrite(ptr, 1, size, fp)) < size) {
if (ferror(fp) && errno == EINTR)
Expand All @@ -233,5 +247,14 @@ download_pkg(char *pkg_url, FILE *fp, int cur, int total)
return -1;
}

if (sha256_expected) {
SHA256_End(&sha256, sha256_actual);
if (strcmp(sha256_expected, sha256_actual) != 0) {
fprintf(stderr, "download error: %s corrupted\n",
pkg_url);
return -1;
}
}

return written;
}
4 changes: 3 additions & 1 deletion pkgin.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ typedef struct Pkglist {
int skip; /* Already processed via a different path */
int keep; /*!< autoremovable package ? */

char *sha256;

SLIST_ENTRY(Pkglist) next;
} Pkglist;

Expand Down Expand Up @@ -361,7 +363,7 @@ Sumfile *sum_open(char *, time_t *);
int sum_start(struct archive *, void *);
ssize_t sum_read(struct archive *, void *, const void **);
int sum_close(struct archive *, void *);
off_t download_pkg(char *, FILE *, int, int);
off_t download_pkg(char *, FILE *, int, int, const char *);
/* summary.c */
int update_db(int, int);
void split_repos(void);
Expand Down
5 changes: 5 additions & 0 deletions pkgin.sql
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ CREATE TABLE [REMOTE_PKG] (
"SIZE_PKG" TEXT,
"FILE_SIZE" TEXT,
"OPSYS" TEXT,
"FILE_CKSUM sha256" TEXT,
"REPOSITORY" TEXT
);

Expand All @@ -45,6 +46,7 @@ CREATE TABLE [LOCAL_PKG] (
"SIZE_PKG" TEXT,
"FILE_SIZE" TEXT,
"OPSYS" TEXT,
"FILE_CKSUM sha256" TEXT,
"PKG_KEEP" INTEGER NULL
);

Expand Down Expand Up @@ -195,3 +197,6 @@ CREATE INDEX [idx_local_pkg_comment] ON [LOCAL_PKG] (
CREATE INDEX [idx_local_pkg_name] ON [LOCAL_PKG] (
[PKGNAME] ASC
);

PRAGMA application_id = 1886087022;
PRAGMA user_version = 2;
34 changes: 33 additions & 1 deletion pkgindb.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,31 @@ pkgindb_savepoint_release(uint64_t savepoint)
}
}

/*
* Check the application_id and user_version parameters.
*/
static int
check_appid(void *param, int argc, char **argv, char **colname)
{

if (argc != 1 || argv == NULL)
return PDB_ERR;
if (strcmp(argv[0], "1886087022") != 0)
return PDB_ERR;
return PDB_OK;
}

static int
check_version(void *param, int argc, char **argv, char **colname)
{

if (argc != 1 || argv == NULL)
return PDB_ERR;
if (strcmp(argv[0], "2") != 0)
return PDB_ERR;
return PDB_OK;
}

/*
* Configure the pkgin database. Returns 0 if opening an existing compatible
* database, or 1 if the database needs to be created or recreated (in the case
Expand Down Expand Up @@ -277,7 +302,14 @@ pkgindb_open(void)
errx(EXIT_FAILURE, "cannot create database: %s",
sqlite3_errmsg(pdb));
} else {
if (pkgindb_doquery(CHECK_DB_LATEST, NULL, NULL) != PDB_OK) {
if (pkgindb_doquery("PRAGMA application_id", check_appid, NULL)
!= PDB_OK) {
if (unlink(pkgin_sqldb) < 0)
err(EXIT_FAILURE, "cannot recreate database");
goto recreate;
}
if (pkgindb_doquery("PRAGMA user_version", check_version, NULL)
!= PDB_OK) {
if (unlink(pkgin_sqldb) < 0)
err(EXIT_FAILURE, "cannot recreate database");
goto recreate;
Expand Down
16 changes: 3 additions & 13 deletions pkgindb_queries.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,6 @@
* SUCH DAMAGE.
*/

/*
* This query checks the compatibility of the current database, and should be
* one that either completes or fails due to an SQL error based on the most
* recent schema change. Returned rows are ignored, so choose a query that
* runs quickly.
*/
const char CHECK_DB_LATEST[] =
"SELECT pkgbase "
" FROM local_conflicts "
" LIMIT 1;";

const char DELETE_LOCAL[] =
"DELETE FROM LOCAL_PKG;"
"DELETE FROM LOCAL_CONFLICTS;"
Expand Down Expand Up @@ -116,14 +105,15 @@ const char UNKEEP_PKG[] =
/* for upgrades, prefer higher versions to be at the top of SLIST */
const char LOCAL_PKGS_QUERY_ASC[] =
"SELECT FULLPKGNAME,PKGNAME,PKGVERS,BUILD_DATE,"
"COMMENT,FILE_SIZE,SIZE_PKG,CATEGORIES,PKGPATH,PKG_KEEP "
"COMMENT,FILE_SIZE,SIZE_PKG,CATEGORIES,PKGPATH,\"FILE_CKSUM sha256\","
"PKG_KEEP "
"FROM LOCAL_PKG "
"ORDER BY FULLPKGNAME ASC;";

/* present packages by repository appearance to avoid conflicts between repos */
const char REMOTE_PKGS_QUERY_ASC[] =
"SELECT FULLPKGNAME,PKGNAME,PKGVERS,BUILD_DATE,"
"COMMENT,FILE_SIZE,SIZE_PKG,CATEGORIES,PKGPATH "
"COMMENT,FILE_SIZE,SIZE_PKG,CATEGORIES,PKGPATH,\"FILE_CKSUM sha256\" "
"FROM REMOTE_PKG "
"INNER JOIN REPOS WHERE REMOTE_PKG.REPOSITORY = REPOS.REPO_URL "
"ORDER BY REPOS.ROWID, FULLPKGNAME ASC;";
Expand Down
5 changes: 4 additions & 1 deletion pkglist.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ malloc_pkglist(void)
pkglist->pkgpath = NULL;
pkglist->skip = 0;
pkglist->keep = 0;
pkglist->sha256 = NULL;
pkglist->action = ACTION_NONE;

return pkglist;
Expand All @@ -118,6 +119,7 @@ free_pkglist_entry(Pkglist **plist)
{
int i;

XFREE((*plist)->sha256);
XFREE((*plist)->pkgfs);
XFREE((*plist)->pkgurl);
XFREE((*plist)->full);
Expand Down Expand Up @@ -189,11 +191,12 @@ record_pkglist(void *param, int argc, char **argv, char **colname)
NUM_OR_NULL(p->size_pkg, argv[6]);
DUP_OR_NULL(p->category, argv[7]);
DUP_OR_NULL(p->pkgpath, argv[8]);
DUP_OR_NULL(p->sha256, argv[9]);

/*
* Only LOCAL_PKG has PKG_KEEP.
*/
if (plist->P_type == 0 && argv[9])
if (plist->P_type == 0 && argv[10])
p->keep = 1;

if (plist->P_type == 1) {
Expand Down
18 changes: 15 additions & 3 deletions summary.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ prepare_insert(int pkgid, struct Summary sum)

/* insert fields */
SLIST_FOREACH(pi, &inserthead, next) {
sqlite3_snprintf(sizeof(tmpbuf), tmpbuf, ",%w", pi->field);
sqlite3_snprintf(sizeof(tmpbuf), tmpbuf, ",\"%w\"", pi->field);
if (strlcat(querybuf, tmpbuf, sizeof(querybuf)) >=
sizeof(querybuf))
goto err;
Expand Down Expand Up @@ -354,7 +354,12 @@ parse_entry(struct Summary sum, int pkgid, char *line)
* Handle remaining columns.
*/
for (i = 0; i < cols.num; i++) {
snprintf(buf, BUFSIZ, "%s=", cols.name[i]);
if (strncmp(cols.name[i], "FILE_CKSUM ", 11) == 0) {
snprintf(buf, BUFSIZ, "FILE_CKSUM=%s ",
cols.name[i] + 11);
} else {
snprintf(buf, BUFSIZ, "%s=", cols.name[i]);
}

if (strncmp(buf, line, strlen(buf)) == 0) {
/* Split PKGNAME into parts */
Expand All @@ -373,8 +378,15 @@ parse_entry(struct Summary sum, int pkgid, char *line)
*v++ = '\0';
add_to_slist("PKGNAME", val);
add_to_slist("PKGVERS", v);
} else
} else {
if (strncmp(cols.name[i], "FILE_CKSUM ", 11)
== 0) {
if ((val = strchr(val, ' ')) == NULL)
return;
val++;
}
add_to_slist(cols.name[i], val);
}
break;
}
}
Expand Down