auc: update to version 0.0.9

* use full package list when checking for upgrades
 * verify sha256sums and usign signature of sha256sums.sig
 * introduce '-c' option to only check if system is up-to-date
 * introduce '-F' option to ignore the signature verification result
 * return -1 on locally caused and -2 on server-side errors
 * don't include locally appended attributes in debug output of a
   server reply
 * output bug report note on 412 target not found
 * use content-length header instead of filesize field in JSON content
 * suppress duplicate error messages
 * drop unused attributes
 * make debug messages optional at compile-time

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
This commit is contained in:
Daniel Golle 2018-02-23 00:35:48 +01:00
parent 2be807285a
commit 8162fecb37
2 changed files with 302 additions and 122 deletions

View File

@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=auc
PKG_VERSION:=0.0.8
PKG_RELEASE=1
PKG_VERSION:=0.0.9
PKG_RELEASE:=1
PKG_LICENSE:=GPL-3.0
include $(INCLUDE_DIR)/package.mk
@ -24,6 +24,12 @@ define Package/auc/description
CLI client for attended-sysupgrade
endef
# set to 1 to enable debugging
DEBUG:=1
EXTRA_CFLAGS += \
$(if $(DEBUG),-DAUC_DEBUG=ON)
define Package/auc/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/auc $(1)/usr/sbin/

View File

@ -13,7 +13,7 @@
*/
#define _GNU_SOURCE
#define AUC_VERSION "0.0.8"
#define AUC_VERSION "0.0.9"
#include <fcntl.h>
#include <dlfcn.h>
@ -39,6 +39,16 @@
#define APIOBJ_CHECK "api/upgrade-check"
#define APIOBJ_REQUEST "api/upgrade-request"
#define PUBKEY_PATH "/etc/opkg/keys"
#ifdef AUC_DEBUG
#define DPRINTF(...) if (debug) fprintf(stderr, __VA_ARGS__)
#else
#define DPRINTF(...)
#endif
static const char server_issues[]="https://github.com/aparcar/attendedsysupgrade-server/issues";
static char user_agent[80];
static char *serverurl;
static int upgrade_packages;
@ -52,30 +62,26 @@ static int output_fd = -1;
static int retry, imagebuilder, building, ibready;
static char *board_name = NULL;
static char *target = NULL, *subtarget = NULL;
static char *distribution = NULL, *version = NULL, *revision = NULL;
static char *distribution = NULL, *version = NULL;
static int uptodate;
static char *filename = NULL;
static int rc;
#ifdef AUC_DEBUG
static int debug = 0;
#endif
/*
* policy for ubus call system board
* see procd/system.c
*/
enum {
BOARD_KERNEL,
BOARD_HOSTNAME,
BOARD_SYSTEM,
BOARD_MODEL,
BOARD_BOARD_NAME,
BOARD_RELEASE,
__BOARD_MAX,
};
static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
[BOARD_KERNEL] = { .name = "kernel", .type = BLOBMSG_TYPE_STRING },
[BOARD_HOSTNAME] = { .name = "hostname", .type = BLOBMSG_TYPE_STRING },
[BOARD_SYSTEM] = { .name = "system", .type = BLOBMSG_TYPE_STRING },
[BOARD_MODEL] = { .name = "model", .type = BLOBMSG_TYPE_STRING },
[BOARD_BOARD_NAME] = { .name = "board_name", .type = BLOBMSG_TYPE_STRING },
[BOARD_RELEASE] = { .name = "release", .type = BLOBMSG_TYPE_TABLE },
};
@ -87,20 +93,14 @@ static const struct blobmsg_policy board_policy[__BOARD_MAX] = {
enum {
RELEASE_DISTRIBUTION,
RELEASE_VERSION,
RELEASE_REVISION,
RELEASE_CODENAME,
RELEASE_TARGET,
RELEASE_DESCRIPTION,
__RELEASE_MAX,
};
static const struct blobmsg_policy release_policy[__RELEASE_MAX] = {
[RELEASE_DISTRIBUTION] = { .name = "distribution", .type = BLOBMSG_TYPE_STRING },
[RELEASE_VERSION] = { .name = "version", .type = BLOBMSG_TYPE_STRING },
[RELEASE_REVISION] = { .name = "revision", .type = BLOBMSG_TYPE_STRING },
[RELEASE_CODENAME] = { .name = "codename", .type = BLOBMSG_TYPE_STRING },
[RELEASE_TARGET] = { .name = "target", .type = BLOBMSG_TYPE_STRING },
[RELEASE_DESCRIPTION] = { .name = "description", .type = BLOBMSG_TYPE_STRING },
};
/*
@ -146,6 +146,11 @@ static const struct blobmsg_policy check_policy[__CHECK_MAX] = {
[CHECK_UPGRADES] = { .name = "upgrades", .type = BLOBMSG_TYPE_TABLE },
};
static const struct blobmsg_policy pkg_upgrades_policy[2] = {
{ .type = BLOBMSG_TYPE_STRING },
{ .type = BLOBMSG_TYPE_STRING },
};
/*
* policy for upgrade-request response
* parse download information for the ready image.
@ -162,19 +167,37 @@ enum {
static const struct blobmsg_policy image_policy[__IMAGE_MAX] = {
[IMAGE_REQHASH] = { .name = "request_hash", .type = BLOBMSG_TYPE_STRING },
[IMAGE_FILESIZE] = { .name = "filesize", .type = BLOBMSG_TYPE_INT32 },
[IMAGE_URL] = { .name = "url", .type = BLOBMSG_TYPE_STRING },
[IMAGE_CHECKSUM] = { .name = "checksum", .type = BLOBMSG_TYPE_STRING },
[IMAGE_FILES] = { .name = "files", .type = BLOBMSG_TYPE_STRING },
[IMAGE_SYSUPGRADE] = { .name = "sysupgrade", .type = BLOBMSG_TYPE_STRING },
};
/*
* policy for HTTP headers received from server
*/
enum {
H_RANGE,
H_LEN,
H_IBSTATUS,
H_IBQUEUEPOS,
H_UNKNOWN_PACKAGE,
__H_MAX
};
static const struct blobmsg_policy policy[__H_MAX] = {
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
[H_UNKNOWN_PACKAGE] = { .name = "x-unknown-package", .type = BLOBMSG_TYPE_STRING },
};
/*
* load serverurl from UCI
*/
static int load_config() {
static struct uci_context *uci_ctx;
static struct uci_package *uci_attendedsysupgrade;
struct uci_context *uci_ctx;
struct uci_package *uci_attendedsysupgrade;
struct uci_section *uci_s;
uci_ctx = uci_alloc_context();
@ -217,20 +240,47 @@ static int load_config() {
* rpc-sys packagelist
* append packagelist response to blobbuf given in req->priv
*/
static void pkglist_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
static void pkglist_check_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
struct blob_buf *buf = (struct blob_buf *)req->priv;
struct blob_attr *tb[__PACKAGELIST_MAX];
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[PACKAGELIST_PACKAGES]) {
fprintf(stderr, "No packagelist received\n");
rc=-1;
return;
}
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
};
/*
* rpc-sys packagelist
* append array of package names to blobbuf given in req->priv
*/
static void pkglist_req_cb(struct ubus_request *req, int type, struct blob_attr *msg) {
struct blob_buf *buf = (struct blob_buf *)req->priv;
struct blob_attr *tb[__PACKAGELIST_MAX];
struct blob_attr *cur;
int rem;
void *array;
blobmsg_parse(packagelist_policy, __PACKAGELIST_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[PACKAGELIST_PACKAGES]) {
fprintf(stderr, "No packagelist received\n");
return;
}
blobmsg_add_field(buf, BLOBMSG_TYPE_TABLE, "packages", blobmsg_data(tb[PACKAGELIST_PACKAGES]), blobmsg_data_len(tb[PACKAGELIST_PACKAGES]));
array = blobmsg_open_array(buf, "packages");
blobmsg_for_each_attr(cur, tb[PACKAGELIST_PACKAGES], rem)
blobmsg_add_string(buf, NULL, blobmsg_name(cur));
blobmsg_close_array(buf, array);
};
/*
* system board
* append append board information to blobbuf given in req->priv
@ -245,12 +295,14 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
if (!tb[BOARD_BOARD_NAME]) {
fprintf(stderr, "No board name received\n");
rc=-1;
return;
}
board_name = strdup(blobmsg_get_string(tb[BOARD_BOARD_NAME]));
if (!tb[BOARD_RELEASE]) {
fprintf(stderr, "No release received\n");
rc=-1;
return;
}
@ -259,6 +311,7 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
if (!rel[RELEASE_TARGET]) {
fprintf(stderr, "No target received\n");
rc=-1;
return;
}
@ -268,7 +321,6 @@ static void board_cb(struct ubus_request *req, int type, struct blob_attr *msg)
distribution = strdup(blobmsg_get_string(rel[RELEASE_DISTRIBUTION]));
version = strdup(blobmsg_get_string(rel[RELEASE_VERSION]));
revision = strdup(blobmsg_get_string(rel[RELEASE_REVISION]));
blobmsg_add_string(buf, "distro", distribution);
blobmsg_add_string(buf, "target", target);
@ -354,19 +406,6 @@ static void request_done(struct uclient *cl)
static void header_done_cb(struct uclient *cl)
{
enum {
H_RANGE,
H_LEN,
H_IBSTATUS,
H_IBQUEUEPOS,
__H_MAX
};
static const struct blobmsg_policy policy[__H_MAX] = {
[H_RANGE] = { .name = "content-range", .type = BLOBMSG_TYPE_STRING },
[H_LEN] = { .name = "content-length", .type = BLOBMSG_TYPE_STRING },
[H_IBSTATUS] = { .name = "x-imagebuilder-status", .type = BLOBMSG_TYPE_STRING },
[H_IBQUEUEPOS] = { .name = "x-build-queue-position", .type = BLOBMSG_TYPE_STRING },
};
struct blob_attr *tb[__H_MAX];
uint64_t resume_offset = 0, resume_end, resume_size;
char *ibstatus;
@ -385,21 +424,24 @@ static void header_done_cb(struct uclient *cl)
return;
}
if (debug)
fprintf(stderr, "headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
DPRINTF("headers:\n%s\n", blobmsg_format_json_indent(cl->meta, true, 0));
blobmsg_parse(policy, __H_MAX, tb, blob_data(cl->meta), blob_len(cl->meta));
switch (cl->status_code) {
case 400:
request_done(cl);
rc=-1;
break;
case 412:
fprintf(stderr, "target not found.\n");
fprintf(stderr, "%s target %s/%s (%s) not found. Please report this at %s\n",
distribution, target, subtarget, board_name, server_issues);
request_done(cl);
rc=-2;
break;
case 413:
fprintf(stderr, "image too big.\n");
rc=-1;
request_done(cl);
break;
case 416:
@ -407,16 +449,20 @@ static void header_done_cb(struct uclient *cl)
request_done(cl);
break;
case 422:
fprintf(stderr, "unknown package requested.\n");
fprintf(stderr, "unknown package '%s' requested.\n",
blobmsg_get_string(tb[H_UNKNOWN_PACKAGE]));
rc=-1;
request_done(cl);
break;
case 501:
fprintf(stderr, "ImageBuilder didn't produce sysupgrade file.\n");
rc=-2;
request_done(cl);
break;
case 204:
fprintf(stderr, "system is up to date.\n");
fprintf(stdout, "system is up to date.\n");
uptodate=1;
request_done(cl);
break;
case 206:
if (!cur_resume) {
@ -467,6 +513,7 @@ static void header_done_cb(struct uclient *cl)
retry=1;
} else {
fprintf(stderr, "unrecognized remote imagebuilder status '%s'\n", ibstatus);
rc=-2;
}
// fall through
case 200:
@ -657,45 +704,95 @@ static int init_ustream_ssl(void) {
}
/**
* use busybox md5sum (from jow's luci-ng)
* use busybox sha256sum to verify sha256sums file
*/
static char *md5sum(const char *file) {
static int sha256sum_v(const char *sha256file, const char *msgfile) {
pid_t pid;
int fds[2];
static char md5[33];
int status;
FILE *f = fopen(sha256file, "r");
char sumline[512] = {};
char *fname;
unsigned int fnlen;
unsigned int cnt = 0;
if (pipe(fds))
return NULL;
return -1;
switch ((pid = fork()))
{
if (!f)
return -1;
pid = fork();
switch (pid) {
case -1:
return NULL;
return -1;
case 0:
uloop_done();
dup2(fds[1], 1);
close(0);
dup2(fds[0], 0);
close(1);
close(2);
close(fds[0]);
close(fds[1]);
if (execl("/bin/busybox", "/bin/busybox", "md5sum", file, NULL));
return NULL;
if (execl("/bin/busybox", "/bin/busybox", "sha256sum", "-s", "-c", NULL));
return -1;
break;
default:
memset(md5, 0, sizeof(md5));
read(fds[0], md5, 32);
waitpid(pid, NULL, 0);
close(fds[0]);
while (fgets(sumline, sizeof(sumline), f)) {
fname = &sumline[66];
fnlen = strlen(fname);
fname[fnlen-1] = '\0';
if (!strcmp(fname, msgfile)) {
fname[fnlen-1] = '\n';
write(fds[1], sumline, strlen(sumline));
cnt++;
}
}
fclose(f);
close(fds[1]);
waitpid(pid, &status, 0);
close(fds[0]);
if (cnt == 1)
return WEXITSTATUS(status);
else
return -1;
}
return md5;
return -1;
}
/**
* use usign to verify sha256sums.sig
*/
static int usign_v(const char *file) {
pid_t pid;
int status;
pid = fork();
switch (pid) {
case -1:
return -1;
case 0:
uloop_done();
if (execl("/usr/bin/usign", "/usr/bin/usign",
"-V", "-q", "-P", PUBKEY_PATH, "-m", file, NULL));
return -1;
break;
default:
waitpid(pid, &status, 0);
return WEXITSTATUS(status);
}
return -1;
}
static int ask_user(void)
@ -711,13 +808,8 @@ static void print_package_updates(struct blob_attr *upgrades) {
struct blob_attr *tb[2];
int rem;
static struct blobmsg_policy policy[2] = {
{ .type = BLOBMSG_TYPE_STRING },
{ .type = BLOBMSG_TYPE_STRING },
};
blobmsg_for_each_attr(cur, upgrades, rem) {
blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
blobmsg_parse_array(pkg_upgrades_policy, ARRAY_SIZE(policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
if (!tb[0] || !tb[1])
continue;
@ -728,19 +820,19 @@ static void print_package_updates(struct blob_attr *upgrades) {
/* this main function is too big... todo: split */
int main(int args, char *argv[]) {
unsigned char argc=1;
static struct blob_buf checkbuf, reqbuf, imgbuf, upgbuf;
static struct blob_buf allpkg, checkbuf, infobuf, reqbuf, imgbuf, upgbuf;
struct ubus_context *ctx = ubus_connect(NULL);
uint32_t id;
int rc;
int queuepos, valid, use_get;
int valid, use_get;
char url[256];
char *newversion = NULL;
struct blob_attr *tb[__IMAGE_MAX];
struct blob_attr *tbc[__CHECK_MAX];
unsigned int filesize;
char *checksum = NULL;
char *tmp;
struct stat imgstat;
int check_only = 0;
int ignore_sig = 0;
unsigned char argc = 1;
snprintf(user_agent, sizeof(user_agent), "%s (%s)", argv[0], AUC_VERSION);
fprintf(stdout, "%s\n", user_agent);
@ -750,12 +842,25 @@ int main(int args, char *argv[]) {
!strncmp(argv[argc], "--help", 7)) {
fprintf(stdout, "%s: Attended sysUpgrade CLI client\n", argv[0]);
fprintf(stdout, "Usage: auc [-d] [-h]\n");
fprintf(stdout, " -c\tonly check if system is up-to-date\n");
fprintf(stdout, " -F\tignore result of signature verification\n");
#ifdef AUC_DEBUG
fprintf(stdout, " -d\tenable debugging output\n");
#endif
fprintf(stdout, " -h\toutput help\n");
return 0;
}
#ifdef AUC_DEBUG
if (!strncmp(argv[argc], "-d", 3))
debug = 1;
#endif
if (!strncmp(argv[argc], "-c", 3))
check_only = 1;
if (!strncmp(argv[argc], "-F", 3))
ignore_sig = 1;
argc++;
};
@ -787,9 +892,12 @@ int main(int args, char *argv[]) {
}
blobmsg_buf_init(&checkbuf);
blobmsg_buf_init(&infobuf);
blobmsg_buf_init(&reqbuf);
blobmsg_buf_init(&imgbuf);
blobmsg_buf_init(&upgbuf);
/* ubus requires BLOBMSG_TYPE_UNSPEC */
blob_buf_init(&allpkg, 0);
blob_buf_init(&upgbuf, 0);
if (ubus_lookup_id(ctx, "system", &id) ||
ubus_invoke(ctx, id, "board", NULL, board_cb, &checkbuf, 3000)) {
@ -798,34 +906,37 @@ int main(int args, char *argv[]) {
goto freebufs;
}
if (rc)
goto freebufs;
blobmsg_add_u8(&allpkg, "all", 1);
blobmsg_add_string(&allpkg, "dummy", "foo");
if (ubus_lookup_id(ctx, "rpc-sys", &id) ||
ubus_invoke(ctx, id, "packagelist", NULL, pkglist_cb, &checkbuf, 3000)) {
ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_check_cb, &checkbuf, 3000)) {
fprintf(stderr, "cannot request packagelist from rpcd\n");
rc=-1;
goto freeboard;
}
if (rc)
goto freeboard;
blobmsg_add_u32(&checkbuf, "upgrade_packages", upgrade_packages);
fprintf(stdout, "running %s %s %s on %s/%s (%s)\n", distribution,
version, revision, target, subtarget, board_name);
fprintf(stdout, "running %s %s on %s/%s (%s)\n", distribution,
version, target, subtarget, board_name);
fprintf(stdout, "checking %s for release upgrade%s\n", serverurl,
upgrade_packages?" or updated packages":"");
blobmsg_add_string(&reqbuf, "distro", distribution);
blobmsg_add_string(&reqbuf, "target", target);
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
blobmsg_add_string(&reqbuf, "board", board_name);
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_CHECK);
uptodate=0;
do {
retry=0;
if (debug)
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
if (server_request(url, &checkbuf, &reqbuf)) {
DPRINTF("requesting:\n%s\n", blobmsg_format_json_indent(checkbuf.head, true, 0));
if (server_request(url, &checkbuf, &infobuf)) {
fprintf(stderr, "failed to connect to server\n");
rc=-1;
goto freeboard;
@ -835,20 +946,20 @@ int main(int args, char *argv[]) {
sleep(3);
} while(retry);
if (debug)
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(infobuf.head, true, 0));
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(reqbuf.head), blob_len(reqbuf.head));
blobmsg_parse(check_policy, __CHECK_MAX, tbc, blob_data(infobuf.head), blob_len(infobuf.head));
if (!tbc[CHECK_VERSION] && !tbc[CHECK_UPGRADES]) {
if (!uptodate) {
if (uptodate) {
rc=0;
} else if (!rc) {
fprintf(stderr, "server reply invalid.\n");
rc=-1;
goto freeboard;
rc=-2;
}
rc=0;
goto freeboard;
}
if (tbc[CHECK_VERSION]) {
newversion = blobmsg_get_string(tbc[CHECK_VERSION]);
fprintf(stdout, "new %s release %s found.\n", distribution, newversion);
@ -862,10 +973,29 @@ int main(int args, char *argv[]) {
print_package_updates(tbc[CHECK_UPGRADES]);
}
if (check_only) {
rc=1;
goto freeboard;
};
rc = ask_user();
if (rc)
goto freeboard;
blobmsg_add_string(&reqbuf, "distro", distribution);
blobmsg_add_string(&reqbuf, "target", target);
blobmsg_add_string(&reqbuf, "subtarget", subtarget);
blobmsg_add_string(&reqbuf, "board", board_name);
blob_buf_init(&allpkg, 0);
blobmsg_add_u8(&allpkg, "all", 0);
blobmsg_add_string(&allpkg, "dummy", "foo");
if (ubus_invoke(ctx, id, "packagelist", allpkg.head, pkglist_req_cb, &reqbuf, 3000)) {
fprintf(stderr, "cannot request packagelist from rpcd\n");
rc=-1;
goto freeboard;
}
snprintf(url, sizeof(url), "%s/%s", serverurl, APIOBJ_REQUEST);
imagebuilder = 0;
@ -875,8 +1005,7 @@ int main(int args, char *argv[]) {
do {
retry = 0;
if (debug && !use_get)
fprintf(stderr, "requesting:\n%s\n", blobmsg_format_json_indent(reqbuf.head, true, 0));
DPRINTF("requesting:\n%s\n", use_get?"":blobmsg_format_json_indent(reqbuf.head, true, 0));
server_request(url, use_get?NULL:&reqbuf, &imgbuf);
blobmsg_parse(image_policy, __IMAGE_MAX, tb, blob_data(imgbuf.head), blob_len(imgbuf.head));
@ -885,9 +1014,7 @@ int main(int args, char *argv[]) {
snprintf(url, sizeof(url), "%s/%s/%s", serverurl,
APIOBJ_REQUEST,
blobmsg_get_string(tb[IMAGE_REQHASH]));
if (debug)
fprintf(stderr, "polling via GET %s\n", url);
DPRINTF("polling via GET %s\n", url);
retry=1;
use_get=1;
}
@ -897,35 +1024,22 @@ int main(int args, char *argv[]) {
blobmsg_buf_init(&imgbuf);
sleep(3);
}
} while(retry || queuepos);
} while(retry);
if (debug)
fprintf(stderr, "reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
DPRINTF("reply:\n%s\n", blobmsg_format_json_indent(imgbuf.head, true, 0));
if (!tb[IMAGE_SYSUPGRADE]) {
fprintf(stderr, "no sysupgrade image returned\n");
rc=-1;
if (!rc) {
fprintf(stderr, "no sysupgrade image returned\n");
rc=-1;
}
goto freeboard;
}
strncpy(url, blobmsg_get_string(tb[IMAGE_SYSUPGRADE]), sizeof(url));
if (!tb[IMAGE_FILESIZE]) {
fprintf(stderr, "no image size returned\n");
rc=-1;
goto freeboard;
}
filesize = blobmsg_get_u32(tb[IMAGE_FILESIZE]);
if (!tb[IMAGE_CHECKSUM]) {
fprintf(stderr, "no image checksum returned\n");
rc=-1;
goto freeboard;
}
checksum = blobmsg_get_string(tb[IMAGE_CHECKSUM]);
server_request(url, NULL, NULL);
/* usign signature is not yet implemented! */
// strncat(url, ".sig", sizeof(url));
// server_request(url, NULL, NULL);
filename = uclient_get_url_filename(url, "firmware.bin");
if (stat(filename, &imgstat)) {
@ -934,18 +1048,78 @@ int main(int args, char *argv[]) {
goto freeboard;
}
if ((intmax_t)imgstat.st_size != filesize) {
if ((intmax_t)imgstat.st_size != out_len) {
fprintf(stderr, "file size mismatch\n");
unlink(filename);
rc=-1;
goto freeboard;
}
if (strncmp(checksum, md5sum(filename), 33)) {
fprintf(stderr, "image checksum mismatch\n");
unlink(filename);
tmp=strrchr(url, '/');
strcpy(tmp, "/sha256sums");
server_request(url, NULL, NULL);
if (stat("sha256sums", &imgstat)) {
fprintf(stderr, "sha256sums download failed\n");
rc=-1;
goto freeboard;
}
if ((intmax_t)imgstat.st_size != out_len) {
fprintf(stderr, "sha256sums download incomplete\n");
unlink("sha256sums");
rc=-1;
goto freeboard;
}
if (out_len < 68) {
fprintf(stderr, "sha256sums size mismatch\n");
unlink("sha256sums");
rc=-1;
goto freeboard;
}
if (sha256sum_v("sha256sums", filename)) {
fprintf(stderr, "checksum verification failed\n");
unlink(filename);
unlink("sha256sums");
rc=-1;
goto freeboard;
}
strcpy(tmp, "/sha256sums.sig");
server_request(url, NULL, NULL);
if (stat("sha256sums.sig", &imgstat)) {
fprintf(stderr, "sha256sums.sig download failed\n");
rc=-1;
goto freeboard;
}
if ((intmax_t)imgstat.st_size != out_len) {
fprintf(stderr, "sha256sums.sig download incomplete\n");
unlink("sha256sums.sig");
rc=-1;
goto freeboard;
}
if (out_len < 16) {
fprintf(stderr, "sha256sums.sig size mismatch\n");
unlink("sha256sums.sig");
rc=-1;
goto freeboard;
}
if (usign_v("sha256sums")) {
fprintf(stderr, "signature verification failed\n");
if (!ignore_sig) {
unlink(filename);
unlink("sha256sums");
unlink("sha256sums.sig");
rc=-1;
goto freeboard;
}
};
if (strcmp(filename, "firmware.bin")) {
@ -974,10 +1148,10 @@ freeboard:
/* subtarget is a pointer within target, don't free */
free(distribution);
free(version);
free(revision);
freebufs:
blob_buf_free(&checkbuf);
blob_buf_free(&infobuf);
blob_buf_free(&reqbuf);
blob_buf_free(&imgbuf);
blob_buf_free(&upgbuf);