Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/pkg_checksum.c
2065 views
1
/* Copyright (c) 2014, Vsevolod Stakhov <[email protected]>
2
* Copyright (c) 2014, Google Inc.
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
7
* * Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* * Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
14
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
17
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
*/
24
25
#include <assert.h>
26
27
#include <sys/stat.h>
28
29
#include <fcntl.h>
30
#include <errno.h>
31
#include "pkg.h"
32
#include "private/pkg.h"
33
#include "private/event.h"
34
#include "sha256.h"
35
#include "blake2.h"
36
37
/* Separate checksum parts */
38
#define PKG_CKSUM_SEPARATOR '$'
39
40
/* Hash is in format <version>:<typeid>:<hexhash> */
41
#define PKG_CHECKSUM_SHA256_LEN (SHA256_BLOCK_SIZE * 2 + 1)
42
#define PKG_CHECKSUM_BLAKE2_LEN (BLAKE2B_OUTBYTES * 8 / 5 + sizeof("100") * 2 + 2)
43
#define PKG_CHECKSUM_BLAKE2S_LEN (BLAKE2S_OUTBYTES * 8 / 5 + sizeof("100") * 2 + 2)
44
#define PKG_CHECKSUM_CUR_VERSION 2
45
46
struct kv {
47
const char *key;
48
const char *value;
49
struct kv *next;
50
};
51
52
struct kv *
53
kv_new(const char *k, const char *v)
54
{
55
struct kv *kv = xcalloc(1, sizeof(*kv));
56
kv->key = k;
57
kv->value = v;
58
return (kv);
59
}
60
61
typedef void (*pkg_checksum_hash_func)(struct kv *entries,
62
unsigned char **out, size_t *outlen);
63
typedef void (*pkg_checksum_hash_bulk_func)(const unsigned char *in, size_t inlen,
64
unsigned char **out, size_t *outlen);
65
typedef void (*pkg_checksum_encode_func)(unsigned char *in, size_t inlen,
66
char *out, size_t outlen);
67
68
typedef void (*pkg_checksum_hash_file_func)(int fd, unsigned char **out,
69
size_t *outlen);
70
71
static void pkg_checksum_hash_sha256(struct kv *entries,
72
unsigned char **out, size_t *outlen);
73
static void pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
74
unsigned char **out, size_t *outlen);
75
static void pkg_checksum_hash_sha256_file(int fd, unsigned char **out,
76
size_t *outlen);
77
static void pkg_checksum_hash_blake2(struct kv *entries,
78
unsigned char **out, size_t *outlen);
79
static void pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
80
unsigned char **out, size_t *outlen);
81
static void pkg_checksum_hash_blake2_file(int fd, unsigned char **out,
82
size_t *outlen);
83
static void pkg_checksum_hash_blake2s(struct kv *entries,
84
unsigned char **out, size_t *outlen);
85
static void pkg_checksum_hash_blake2s_bulk(const unsigned char *in, size_t inlen,
86
unsigned char **out, size_t *outlen);
87
static void pkg_checksum_hash_blake2s_file(int fd, unsigned char **out,
88
size_t *outlen);
89
static void pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
90
char *out, size_t outlen);
91
static void pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
92
char *out, size_t outlen);
93
94
static const struct _pkg_cksum_type {
95
const char *name;
96
size_t hlen;
97
pkg_checksum_hash_func hfunc;
98
pkg_checksum_hash_bulk_func hbulkfunc;
99
pkg_checksum_hash_file_func hfilefunc;
100
pkg_checksum_encode_func encfunc;
101
} checksum_types[] = {
102
[PKG_HASH_TYPE_SHA256_BASE32] = {
103
"sha256_base32",
104
PKG_CHECKSUM_SHA256_LEN,
105
pkg_checksum_hash_sha256,
106
pkg_checksum_hash_sha256_bulk,
107
pkg_checksum_hash_sha256_file,
108
pkg_checksum_encode_base32
109
},
110
[PKG_HASH_TYPE_SHA256_HEX] = {
111
"sha256_hex",
112
PKG_CHECKSUM_SHA256_LEN,
113
pkg_checksum_hash_sha256,
114
pkg_checksum_hash_sha256_bulk,
115
pkg_checksum_hash_sha256_file,
116
pkg_checksum_encode_hex
117
},
118
[PKG_HASH_TYPE_BLAKE2_BASE32] = {
119
"blake2_base32",
120
PKG_CHECKSUM_BLAKE2_LEN,
121
pkg_checksum_hash_blake2,
122
pkg_checksum_hash_blake2_bulk,
123
pkg_checksum_hash_blake2_file,
124
pkg_checksum_encode_base32
125
},
126
[PKG_HASH_TYPE_SHA256_RAW] = {
127
"sha256_raw",
128
SHA256_BLOCK_SIZE,
129
pkg_checksum_hash_sha256,
130
pkg_checksum_hash_sha256_bulk,
131
pkg_checksum_hash_sha256_file,
132
NULL
133
},
134
[PKG_HASH_TYPE_BLAKE2_RAW] = {
135
"blake2_raw",
136
BLAKE2B_OUTBYTES,
137
pkg_checksum_hash_blake2,
138
pkg_checksum_hash_blake2_bulk,
139
pkg_checksum_hash_blake2_file,
140
NULL
141
},
142
[PKG_HASH_TYPE_BLAKE2S_BASE32] = {
143
"blake2s_base32",
144
PKG_CHECKSUM_BLAKE2S_LEN,
145
pkg_checksum_hash_blake2s,
146
pkg_checksum_hash_blake2s_bulk,
147
pkg_checksum_hash_blake2s_file,
148
pkg_checksum_encode_base32
149
},
150
[PKG_HASH_TYPE_BLAKE2S_RAW] = {
151
"blake2s_raw",
152
BLAKE2S_OUTBYTES,
153
pkg_checksum_hash_blake2s,
154
pkg_checksum_hash_blake2s_bulk,
155
pkg_checksum_hash_blake2s_file,
156
NULL
157
},
158
[PKG_HASH_TYPE_UNKNOWN] = {
159
NULL,
160
-1,
161
NULL,
162
NULL,
163
NULL
164
}
165
};
166
167
static int
168
pkg_checksum_entry_cmp(struct kv *e1,
169
struct kv *e2)
170
{
171
int r;
172
173
/* Compare field names first. */
174
r = strcmp(e1->key, e2->key);
175
if (r != 0)
176
return r;
177
178
/* If field names are the same, compare values. */
179
return (strcmp(e1->value, e2->value));
180
}
181
182
/*
183
* At the moment we use the following fields to calculate the unique checksum
184
* of the following fields:
185
* - name
186
* - origin
187
* - version
188
* - arch
189
* - options
190
* - required_shlibs
191
* - provided_shlibs
192
* - users
193
* - groups
194
* - dependencies
195
*/
196
197
int
198
pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
199
pkg_checksum_type_t type, bool inc_scripts, bool inc_version, bool inc_files __unused)
200
{
201
unsigned char *bdigest;
202
char *olduid;
203
size_t blen;
204
struct kv *entries = NULL;
205
charv_t tofree = vec_init();
206
struct pkg_option *option = NULL;
207
struct pkg_dep *dep = NULL;
208
struct pkg_file *f = NULL;
209
bool is_group = false;
210
211
if (pkg == NULL || type >= PKG_HASH_TYPE_UNKNOWN ||
212
destlen < checksum_types[type].hlen)
213
return (EPKG_FATAL);
214
if (pkg_type(pkg) == PKG_GROUP_REMOTE || pkg_type(pkg) == PKG_GROUP_INSTALLED)
215
is_group = true;
216
217
LL_APPEND(entries, kv_new("name", pkg->name));
218
if (!is_group)
219
LL_APPEND(entries, kv_new("origin", pkg->origin));
220
if (inc_version && !is_group)
221
LL_APPEND(entries, kv_new("version", pkg->version));
222
if (!is_group)
223
LL_APPEND(entries, kv_new("arch", pkg->altabi));
224
225
while (pkg_options(pkg, &option) == EPKG_OK) {
226
LL_APPEND(entries, kv_new(option->key, option->value));
227
}
228
229
vec_foreach(pkg->shlibs_required, i) {
230
LL_APPEND(entries, kv_new("required_shlib", pkg->shlibs_required.d[i]));
231
}
232
233
vec_foreach(pkg->shlibs_provided, i) {
234
LL_APPEND(entries, kv_new("provided_shlib", pkg->shlibs_provided.d[i]));
235
}
236
237
vec_foreach(pkg->users, i) {
238
LL_APPEND(entries, kv_new("user", pkg->users.d[i]));
239
}
240
241
vec_foreach(pkg->groups, i) {
242
LL_APPEND(entries, kv_new("group", pkg->groups.d[i]));
243
}
244
245
while (pkg_deps(pkg, &dep) == EPKG_OK) {
246
if (is_group) {
247
LL_APPEND(entries, kv_new("depend", dep->name));
248
} else {
249
xasprintf(&olduid, "%s~%s", dep->name, dep->origin);
250
LL_APPEND(entries, kv_new("depend", olduid));
251
vec_push(&tofree, olduid);
252
}
253
}
254
255
vec_foreach(pkg->provides, i) {
256
LL_APPEND(entries, kv_new("provide", pkg->provides.d[i]));
257
}
258
259
vec_foreach(pkg->requires, i) {
260
LL_APPEND(entries, kv_new("require", pkg->requires.d[i]));
261
}
262
263
if (inc_scripts) {
264
for (int i = 0; i < PKG_NUM_SCRIPTS; i++) {
265
if (pkg->scripts[i] != NULL) {
266
fflush(pkg->scripts[i]->fp);
267
LL_APPEND(entries, kv_new("script", pkg->scripts[i]->buf));
268
}
269
}
270
for (int i = 0; i < PKG_NUM_LUA_SCRIPTS; i++) {
271
vec_foreach(pkg->lua_scripts[i], j)
272
LL_APPEND(entries, kv_new("lua_script", pkg->lua_scripts[i].d[j]));
273
}
274
}
275
276
while (pkg_files(pkg, &f) == EPKG_OK) {
277
LL_APPEND(entries, kv_new(f->path, f->sum));
278
}
279
280
/* Sort before hashing */
281
LL_SORT(entries, pkg_checksum_entry_cmp);
282
283
checksum_types[type].hfunc(entries, &bdigest, &blen);
284
if (blen == 0 || bdigest == NULL) {
285
LL_FREE(entries, free);
286
vec_free_and_free(&tofree, free);
287
return (EPKG_FATAL);
288
}
289
290
if (checksum_types[type].encfunc) {
291
size_t i = snprintf(dest, destlen, "%d%c%d%c", PKG_CHECKSUM_CUR_VERSION,
292
PKG_CKSUM_SEPARATOR, type, PKG_CKSUM_SEPARATOR);
293
assert(i < destlen);
294
checksum_types[type].encfunc(bdigest, blen, dest + i, destlen - i);
295
}
296
else {
297
/* For raw formats we just output digest */
298
assert(destlen >= blen);
299
memcpy(dest, bdigest, blen);
300
}
301
302
free(bdigest);
303
LL_FREE(entries, free);
304
vec_free_and_free(&tofree, free);
305
306
return (EPKG_OK);
307
}
308
309
bool
310
pkg_checksum_is_valid(const char *cksum, size_t clen)
311
{
312
const char *sep;
313
unsigned int value;
314
315
if (clen < 4)
316
return (false);
317
318
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
319
if (sep == NULL || *sep == '\0')
320
return (false);
321
322
/* Test version */
323
value = strtoul(cksum, NULL, 10);
324
if (value != PKG_CHECKSUM_CUR_VERSION)
325
return (false);
326
327
cksum = sep + 1;
328
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
329
if (sep == NULL || *sep == '\0')
330
return (false);
331
332
/* Test type */
333
value = strtoul(cksum, NULL, 10);
334
if (value >= PKG_HASH_TYPE_UNKNOWN)
335
return (false);
336
337
return (true);
338
}
339
340
/* <hashtype>$<hash> */
341
pkg_checksum_type_t
342
pkg_checksum_file_get_type(const char *cksum, size_t clen __unused)
343
{
344
unsigned int value;
345
346
if (strchr(cksum, PKG_CKSUM_SEPARATOR) == NULL)
347
return (PKG_HASH_TYPE_UNKNOWN);
348
349
value = strtoul(cksum, NULL, 10);
350
if (value < PKG_HASH_TYPE_UNKNOWN)
351
return (value);
352
353
return (PKG_HASH_TYPE_UNKNOWN);
354
}
355
356
/* <version>$<hashtype>$<hash> */
357
pkg_checksum_type_t
358
pkg_checksum_get_type(const char *cksum, size_t clen __unused)
359
{
360
const char *sep;
361
unsigned int value;
362
363
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
364
if (sep != NULL && *sep != '\0') {
365
value = strtoul(sep + 1, NULL, 10);
366
if (value < PKG_HASH_TYPE_UNKNOWN)
367
return (value);
368
}
369
370
return (PKG_HASH_TYPE_UNKNOWN);
371
}
372
373
static void
374
pkg_checksum_hash_sha256(struct kv *entries,
375
unsigned char **out, size_t *outlen)
376
{
377
SHA256_CTX sign_ctx;
378
struct kv *e;
379
380
sha256_init(&sign_ctx);
381
382
LL_FOREACH(entries, e) {
383
sha256_update(&sign_ctx, e->key, strlen(e->key));
384
sha256_update(&sign_ctx, e->value, strlen(e->value));
385
}
386
*out = xmalloc(SHA256_BLOCK_SIZE);
387
sha256_final(&sign_ctx, *out);
388
*outlen = SHA256_BLOCK_SIZE;
389
}
390
391
static void
392
pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
393
unsigned char **out, size_t *outlen)
394
{
395
SHA256_CTX sign_ctx;
396
397
*out = xmalloc(SHA256_BLOCK_SIZE);
398
sha256_init(&sign_ctx);
399
sha256_update(&sign_ctx, in, inlen);
400
sha256_final(&sign_ctx, *out);
401
*outlen = SHA256_BLOCK_SIZE;
402
}
403
404
static void
405
pkg_checksum_hash_sha256_file(int fd, unsigned char **out, size_t *outlen)
406
{
407
char buffer[8192];
408
ssize_t r;
409
410
SHA256_CTX sign_ctx;
411
*out = xmalloc(SHA256_BLOCK_SIZE);
412
sha256_init(&sign_ctx);
413
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
414
sha256_update(&sign_ctx, buffer, r);
415
if (r < 0) {
416
pkg_emit_errno(__func__, "read failed");
417
free(*out);
418
*out = NULL;
419
return;
420
}
421
sha256_final(&sign_ctx, *out);
422
*outlen = SHA256_BLOCK_SIZE;
423
}
424
425
static void
426
pkg_checksum_hash_blake2(struct kv *entries,
427
unsigned char **out, size_t *outlen)
428
{
429
blake2b_state st;
430
struct kv *e;
431
432
blake2b_init (&st, BLAKE2B_OUTBYTES);
433
434
LL_FOREACH(entries, e) {
435
blake2b_update (&st, e->key, strlen(e->key));
436
blake2b_update (&st, e->value, strlen(e->value));
437
}
438
*out = xmalloc(BLAKE2B_OUTBYTES);
439
blake2b_final (&st, *out, BLAKE2B_OUTBYTES);
440
*outlen = BLAKE2B_OUTBYTES;
441
}
442
443
static void
444
pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
445
unsigned char **out, size_t *outlen)
446
{
447
*out = xmalloc(BLAKE2B_OUTBYTES);
448
blake2b(*out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0);
449
*outlen = BLAKE2B_OUTBYTES;
450
}
451
452
static void
453
pkg_checksum_hash_blake2_file(int fd, unsigned char **out, size_t *outlen)
454
{
455
char buffer[8192];
456
ssize_t r;
457
458
blake2b_state st;
459
blake2b_init(&st, BLAKE2B_OUTBYTES);
460
461
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
462
blake2b_update(&st, buffer, r);
463
if (r < 0) {
464
pkg_emit_errno(__func__, "read failed");
465
free(*out);
466
*out = NULL;
467
return;
468
}
469
*out = xmalloc(BLAKE2B_OUTBYTES);
470
blake2b_final(&st, *out, BLAKE2B_OUTBYTES);
471
*outlen = BLAKE2B_OUTBYTES;
472
}
473
474
static void
475
pkg_checksum_hash_blake2s(struct kv *entries,
476
unsigned char **out, size_t *outlen)
477
{
478
blake2s_state st;
479
struct kv *e;
480
481
blake2s_init (&st, BLAKE2S_OUTBYTES);
482
483
LL_FOREACH(entries, e) {
484
blake2s_update (&st, e->key, strlen(e->key));
485
blake2s_update (&st, e->value, strlen(e->value));
486
}
487
*out = xmalloc(BLAKE2S_OUTBYTES);
488
blake2s_final (&st, *out, BLAKE2S_OUTBYTES);
489
*outlen = BLAKE2S_OUTBYTES;
490
}
491
492
static void
493
pkg_checksum_hash_blake2s_bulk(const unsigned char *in, size_t inlen,
494
unsigned char **out, size_t *outlen)
495
{
496
*out = xmalloc(BLAKE2S_OUTBYTES);
497
blake2s(*out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0);
498
*outlen = BLAKE2S_OUTBYTES;
499
}
500
501
static void
502
pkg_checksum_hash_blake2s_file(int fd, unsigned char **out, size_t *outlen)
503
{
504
char buffer[8192];
505
ssize_t r;
506
507
blake2s_state st;
508
blake2s_init(&st, BLAKE2S_OUTBYTES);
509
510
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
511
blake2s_update(&st, buffer, r);
512
if (r < 0) {
513
pkg_emit_errno(__func__, "read failed");
514
free(*out);
515
*out = NULL;
516
return;
517
}
518
*out = xmalloc(BLAKE2S_OUTBYTES);
519
blake2s_final(&st, *out, BLAKE2S_OUTBYTES);
520
*outlen = BLAKE2S_OUTBYTES;
521
}
522
523
/*
524
* We use here z-base32 encoding described here:
525
* http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
526
*/
527
static const char b32[]="ybndrfg8ejkmcpqxot1uwisza345h769";
528
529
530
static void
531
pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
532
char *out, size_t outlen)
533
{
534
int i, remain = -1, r, x;
535
536
if (outlen < inlen * 8 / 5) {
537
pkg_emit_error("cannot encode base32 as outlen is not sufficient");
538
return;
539
}
540
541
for (i = 0, r = 0; i < inlen; i++) {
542
switch (i % 5) {
543
case 0:
544
/* 8 bits of input and 3 to remain */
545
x = in[i];
546
remain = in[i] >> 5;
547
out[r++] = b32[x & 0x1F];
548
break;
549
case 1:
550
/* 11 bits of input, 1 to remain */
551
x = remain | in[i] << 3;
552
out[r++] = b32[x & 0x1F];
553
out[r++] = b32[x >> 5 & 0x1F];
554
remain = x >> 10;
555
break;
556
case 2:
557
/* 9 bits of input, 4 to remain */
558
x = remain | in[i] << 1;
559
out[r++] = b32[x & 0x1F];
560
remain = x >> 5;
561
break;
562
case 3:
563
/* 12 bits of input, 2 to remain */
564
x = remain | in[i] << 4;
565
out[r++] = b32[x & 0x1F];
566
out[r++] = b32[x >> 5 & 0x1F];
567
remain = x >> 10 & 0x3;
568
break;
569
case 4:
570
/* 10 bits of output, nothing to remain */
571
x = remain | in[i] << 2;
572
out[r++] = b32[x & 0x1F];
573
out[r++] = b32[x >> 5 & 0x1F];
574
remain = -1;
575
break;
576
default:
577
/* Not to be happen */
578
break;
579
}
580
581
}
582
if (remain >= 0)
583
out[r++] = b32[remain];
584
585
out[r] = 0;
586
}
587
588
static void
589
pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
590
char *out, size_t outlen)
591
{
592
int i;
593
594
if (outlen < inlen * 2) {
595
pkg_emit_error("cannot encode hex as outlen is not sufficient");
596
return;
597
}
598
599
for (i = 0; i < inlen; i++)
600
sprintf(out + (i * 2), "%02x", in[i]);
601
602
out[inlen * 2] = '\0';
603
}
604
605
pkg_checksum_type_t
606
pkg_checksum_type_from_string(const char *name)
607
{
608
int i;
609
for (i = 0; i < PKG_HASH_TYPE_UNKNOWN; i ++) {
610
if (STRIEQ(name, checksum_types[i].name))
611
return (i);
612
}
613
614
return (PKG_HASH_TYPE_UNKNOWN);
615
}
616
617
const char*
618
pkg_checksum_type_to_string(pkg_checksum_type_t type)
619
{
620
return (checksum_types[type].name);
621
}
622
623
size_t
624
pkg_checksum_type_size(pkg_checksum_type_t type)
625
{
626
return (checksum_types[type].hlen);
627
}
628
629
int
630
pkg_checksum_calculate(struct pkg *pkg, struct pkgdb *db, bool inc_scripts,
631
bool inc_version, bool inc_files)
632
{
633
char *new_digest;
634
struct pkg_repo *repo;
635
int rc = EPKG_OK;
636
pkg_checksum_type_t type;
637
638
if (sizeof(void *) == 8)
639
type = PKG_HASH_TYPE_BLAKE2_BASE32;
640
else
641
type = PKG_HASH_TYPE_BLAKE2S_BASE32;
642
643
if (pkg->reponame != NULL) {
644
repo = pkg_repo_find(pkg->reponame);
645
646
if (repo != NULL)
647
type = repo->meta->digest_format;
648
}
649
650
new_digest = xmalloc(pkg_checksum_type_size(type));
651
if (pkg_checksum_generate(pkg, new_digest, pkg_checksum_type_size(type),
652
type, inc_scripts, inc_version, inc_files)
653
!= EPKG_OK) {
654
free(new_digest);
655
return (EPKG_FATAL);
656
}
657
658
free(pkg->digest);
659
pkg->digest = new_digest;
660
661
if (db != NULL)
662
pkgdb_set_pkg_digest(db, pkg);
663
664
return (rc);
665
}
666
667
668
unsigned char *
669
pkg_checksum_data(const unsigned char *in, size_t inlen,
670
pkg_checksum_type_t type)
671
{
672
const struct _pkg_cksum_type *cksum;
673
unsigned char *out, *res = NULL;
674
size_t outlen;
675
676
if (type >= PKG_HASH_TYPE_UNKNOWN || in == NULL)
677
return (NULL);
678
679
/* Zero terminated string */
680
if (inlen == 0) {
681
inlen = strlen(in);
682
}
683
684
cksum = &checksum_types[type];
685
686
cksum->hbulkfunc(in, inlen, &out, &outlen);
687
if (out != NULL) {
688
if (cksum->encfunc != NULL) {
689
res = xmalloc(cksum->hlen);
690
cksum->encfunc(out, outlen, res, cksum->hlen);
691
free(out);
692
}
693
else {
694
res = out;
695
}
696
}
697
698
return (res);
699
}
700
701
unsigned char *
702
pkg_checksum_fileat(int rootfd, const char *path, pkg_checksum_type_t type)
703
{
704
int fd;
705
unsigned char *ret;
706
707
if ((fd = openat(rootfd, path, O_RDONLY)) == -1) {
708
pkg_emit_errno("open", path);
709
return (NULL);
710
}
711
712
ret = pkg_checksum_fd(fd, type);
713
714
close(fd);
715
716
return (ret);
717
}
718
719
unsigned char *
720
pkg_checksum_file(const char *path, pkg_checksum_type_t type)
721
{
722
return pkg_checksum_fileat(AT_FDCWD, path, type);
723
}
724
725
unsigned char *
726
pkg_checksum_fd(int fd, pkg_checksum_type_t type)
727
{
728
const struct _pkg_cksum_type *cksum;
729
unsigned char *out, *res = NULL;
730
size_t outlen;
731
732
if (type >= PKG_HASH_TYPE_UNKNOWN || fd < 0)
733
return (NULL);
734
735
cksum = &checksum_types[type];
736
cksum->hfilefunc(fd, &out, &outlen);
737
if (out != NULL) {
738
if (cksum->encfunc != NULL) {
739
res = xmalloc(cksum->hlen);
740
cksum->encfunc(out, outlen, res, cksum->hlen);
741
free(out);
742
} else {
743
res = out;
744
}
745
}
746
747
return (res);
748
}
749
750
static unsigned char *
751
pkg_checksum_symlink_readlink(const char *linkbuf, int linklen,
752
pkg_checksum_type_t type)
753
{
754
const char *lnk;
755
756
lnk = linkbuf;
757
758
/*
759
* It is known that \0 is added to the checksum in case the symlink
760
* targets an absolute path but the behaviour is kept for compat
761
*/
762
return (pkg_checksum_data(RELATIVE_PATH(lnk), linklen, type));
763
}
764
765
unsigned char *
766
pkg_checksum_symlink(const char *path, pkg_checksum_type_t type)
767
{
768
return pkg_checksum_symlinkat(AT_FDCWD, path, type);
769
}
770
771
unsigned char *
772
pkg_checksum_symlinkat(int fd, const char *path, pkg_checksum_type_t type)
773
{
774
char linkbuf[MAXPATHLEN];
775
int linklen;
776
777
if ((linklen = readlinkat(fd, path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
778
pkg_emit_errno("pkg_checksum_symlinkat", "readlink failed");
779
return (NULL);
780
}
781
linkbuf[linklen] = '\0';
782
783
return (pkg_checksum_symlink_readlink(linkbuf, linklen, type));
784
}
785
786
int
787
pkg_checksum_validate_file(const char *path, const char *sum)
788
{
789
return pkg_checksum_validate_fileat(AT_FDCWD, path, sum);
790
}
791
792
int
793
pkg_checksum_validate_fileat(int rootfd, const char *path, const char *sum)
794
{
795
struct stat st;
796
char *newsum;
797
pkg_checksum_type_t type;
798
799
type = pkg_checksum_file_get_type(sum, strlen(sum));
800
if (type == PKG_HASH_TYPE_UNKNOWN) {
801
type = PKG_HASH_TYPE_SHA256_HEX;
802
} else {
803
sum = strchr(sum, PKG_CKSUM_SEPARATOR);
804
if (sum != NULL)
805
sum++;
806
}
807
808
if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
809
return (errno);
810
}
811
812
if (S_ISLNK(st.st_mode))
813
newsum = pkg_checksum_symlinkat(rootfd, path, type);
814
else
815
newsum = pkg_checksum_fileat(rootfd, path, type);
816
817
if (newsum == NULL)
818
return (-1);
819
820
if (!STREQ(sum, newsum)) {
821
free(newsum);
822
return (-1);
823
}
824
825
free(newsum);
826
827
return (0);
828
}
829
830
char *
831
pkg_checksum_generate_file(const char *path, pkg_checksum_type_t type)
832
{
833
return pkg_checksum_generate_fileat(AT_FDCWD, path, type);
834
}
835
836
char *
837
pkg_checksum_generate_fileat(int rootfd, const char *path,
838
pkg_checksum_type_t type)
839
{
840
struct stat st;
841
unsigned char *sum;
842
char *cksum;
843
844
if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
845
pkg_emit_errno("pkg_checksum_generate_file", "lstat");
846
return (NULL);
847
}
848
849
if (S_ISLNK(st.st_mode))
850
sum = pkg_checksum_symlinkat(rootfd, path, type);
851
else
852
sum = pkg_checksum_fileat(rootfd, path, type);
853
854
if (sum == NULL)
855
return (NULL);
856
857
xasprintf(&cksum, "%d%c%s", type, PKG_CKSUM_SEPARATOR, sum);
858
free(sum);
859
860
return (cksum);
861
}
862
863