Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/pkg
Path: blob/main/libpkg/pkg_checksum.c
2645 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
* - vital flag
190
* - options
191
* - required_shlibs
192
* - provided_shlibs
193
* - users
194
* - groups
195
* - dependencies
196
*/
197
198
int
199
pkg_checksum_generate(struct pkg *pkg, char *dest, size_t destlen,
200
pkg_checksum_type_t type, bool inc_scripts, bool inc_version, bool inc_files __unused)
201
{
202
unsigned char *bdigest;
203
char *olduid;
204
size_t blen;
205
struct kv *entries = NULL;
206
charv_t tofree = vec_init();
207
struct pkg_option *option = NULL;
208
struct pkg_dep *dep = NULL;
209
struct pkg_file *f = NULL;
210
bool is_group = false;
211
212
if (pkg == NULL || type >= PKG_HASH_TYPE_UNKNOWN ||
213
destlen < checksum_types[type].hlen)
214
return (EPKG_FATAL);
215
if (pkg_type(pkg) == PKG_GROUP_REMOTE || pkg_type(pkg) == PKG_GROUP_INSTALLED)
216
is_group = true;
217
218
LL_APPEND(entries, kv_new("name", pkg->name));
219
if (!is_group)
220
LL_APPEND(entries, kv_new("origin", pkg->origin));
221
if (inc_version && !is_group)
222
LL_APPEND(entries, kv_new("version", pkg->version));
223
if (!is_group)
224
LL_APPEND(entries, kv_new("arch", pkg->altabi));
225
226
LL_APPEND(entries, kv_new("vital", pkg->vital ? "1" : "0"));
227
228
while (pkg_options(pkg, &option) == EPKG_OK) {
229
LL_APPEND(entries, kv_new(option->key, option->value));
230
}
231
232
vec_foreach(pkg->shlibs_required, i) {
233
LL_APPEND(entries, kv_new("required_shlib", pkg->shlibs_required.d[i]));
234
}
235
236
vec_foreach(pkg->shlibs_provided, i) {
237
LL_APPEND(entries, kv_new("provided_shlib", pkg->shlibs_provided.d[i]));
238
}
239
240
vec_foreach(pkg->users, i) {
241
LL_APPEND(entries, kv_new("user", pkg->users.d[i]));
242
}
243
244
vec_foreach(pkg->groups, i) {
245
LL_APPEND(entries, kv_new("group", pkg->groups.d[i]));
246
}
247
248
while (pkg_deps(pkg, &dep) == EPKG_OK) {
249
if (is_group) {
250
LL_APPEND(entries, kv_new("depend", dep->name));
251
} else {
252
xasprintf(&olduid, "%s~%s", dep->name, dep->origin);
253
LL_APPEND(entries, kv_new("depend", olduid));
254
vec_push(&tofree, olduid);
255
}
256
}
257
258
vec_foreach(pkg->provides, i) {
259
LL_APPEND(entries, kv_new("provide", pkg->provides.d[i]));
260
}
261
262
vec_foreach(pkg->requires, i) {
263
LL_APPEND(entries, kv_new("require", pkg->requires.d[i]));
264
}
265
266
if (inc_scripts) {
267
for (int i = 0; i < PKG_NUM_SCRIPTS; i++) {
268
if (pkg->scripts[i] != NULL) {
269
fflush(pkg->scripts[i]->fp);
270
LL_APPEND(entries, kv_new("script", pkg->scripts[i]->buf));
271
}
272
}
273
for (int i = 0; i < PKG_NUM_LUA_SCRIPTS; i++) {
274
vec_foreach(pkg->lua_scripts[i], j)
275
LL_APPEND(entries, kv_new("lua_script", pkg->lua_scripts[i].d[j]));
276
}
277
}
278
279
while (pkg_files(pkg, &f) == EPKG_OK) {
280
LL_APPEND(entries, kv_new(f->path, f->sum != NULL ? f->sum : "" ));
281
}
282
283
/* Sort before hashing */
284
LL_SORT(entries, pkg_checksum_entry_cmp);
285
286
checksum_types[type].hfunc(entries, &bdigest, &blen);
287
if (blen == 0 || bdigest == NULL) {
288
LL_FREE(entries, free);
289
vec_free_and_free(&tofree, free);
290
return (EPKG_FATAL);
291
}
292
293
if (checksum_types[type].encfunc) {
294
size_t i = snprintf(dest, destlen, "%d%c%d%c", PKG_CHECKSUM_CUR_VERSION,
295
PKG_CKSUM_SEPARATOR, type, PKG_CKSUM_SEPARATOR);
296
assert(i < destlen);
297
checksum_types[type].encfunc(bdigest, blen, dest + i, destlen - i);
298
}
299
else {
300
/* For raw formats we just output digest */
301
assert(destlen >= blen);
302
memcpy(dest, bdigest, blen);
303
}
304
305
free(bdigest);
306
LL_FREE(entries, free);
307
vec_free_and_free(&tofree, free);
308
309
return (EPKG_OK);
310
}
311
312
bool
313
pkg_checksum_is_valid(const char *cksum, size_t clen)
314
{
315
const char *sep;
316
unsigned int value;
317
318
if (clen < 4)
319
return (false);
320
321
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
322
if (sep == NULL || *sep == '\0')
323
return (false);
324
325
/* Test version */
326
value = strtoul(cksum, NULL, 10);
327
if (value != PKG_CHECKSUM_CUR_VERSION)
328
return (false);
329
330
cksum = sep + 1;
331
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
332
if (sep == NULL || *sep == '\0')
333
return (false);
334
335
/* Test type */
336
value = strtoul(cksum, NULL, 10);
337
if (value >= PKG_HASH_TYPE_UNKNOWN)
338
return (false);
339
340
return (true);
341
}
342
343
/* <hashtype>$<hash> */
344
pkg_checksum_type_t
345
pkg_checksum_file_get_type(const char *cksum, size_t clen __unused)
346
{
347
unsigned int value;
348
349
if (strchr(cksum, PKG_CKSUM_SEPARATOR) == NULL)
350
return (PKG_HASH_TYPE_UNKNOWN);
351
352
value = strtoul(cksum, NULL, 10);
353
if (value < PKG_HASH_TYPE_UNKNOWN)
354
return (value);
355
356
return (PKG_HASH_TYPE_UNKNOWN);
357
}
358
359
/* <version>$<hashtype>$<hash> */
360
pkg_checksum_type_t
361
pkg_checksum_get_type(const char *cksum, size_t clen __unused)
362
{
363
const char *sep;
364
unsigned int value;
365
366
sep = strchr(cksum, PKG_CKSUM_SEPARATOR);
367
if (sep != NULL && *sep != '\0') {
368
value = strtoul(sep + 1, NULL, 10);
369
if (value < PKG_HASH_TYPE_UNKNOWN)
370
return (value);
371
}
372
373
return (PKG_HASH_TYPE_UNKNOWN);
374
}
375
376
static void
377
pkg_checksum_hash_sha256(struct kv *entries,
378
unsigned char **out, size_t *outlen)
379
{
380
SHA256_CTX sign_ctx;
381
struct kv *e;
382
383
sha256_init(&sign_ctx);
384
385
LL_FOREACH(entries, e) {
386
sha256_update(&sign_ctx, e->key, strlen(e->key));
387
sha256_update(&sign_ctx, e->value, strlen(e->value));
388
}
389
*out = xmalloc(SHA256_BLOCK_SIZE);
390
sha256_final(&sign_ctx, *out);
391
*outlen = SHA256_BLOCK_SIZE;
392
}
393
394
static void
395
pkg_checksum_hash_sha256_bulk(const unsigned char *in, size_t inlen,
396
unsigned char **out, size_t *outlen)
397
{
398
SHA256_CTX sign_ctx;
399
400
*out = xmalloc(SHA256_BLOCK_SIZE);
401
sha256_init(&sign_ctx);
402
sha256_update(&sign_ctx, in, inlen);
403
sha256_final(&sign_ctx, *out);
404
*outlen = SHA256_BLOCK_SIZE;
405
}
406
407
static void
408
pkg_checksum_hash_sha256_file(int fd, unsigned char **out, size_t *outlen)
409
{
410
char buffer[8192];
411
ssize_t r;
412
413
SHA256_CTX sign_ctx;
414
*out = xmalloc(SHA256_BLOCK_SIZE);
415
sha256_init(&sign_ctx);
416
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
417
sha256_update(&sign_ctx, buffer, r);
418
if (r < 0) {
419
pkg_emit_errno(__func__, "read failed");
420
free(*out);
421
*out = NULL;
422
return;
423
}
424
sha256_final(&sign_ctx, *out);
425
*outlen = SHA256_BLOCK_SIZE;
426
}
427
428
static void
429
pkg_checksum_hash_blake2(struct kv *entries,
430
unsigned char **out, size_t *outlen)
431
{
432
blake2b_state st;
433
struct kv *e;
434
435
blake2b_init (&st, BLAKE2B_OUTBYTES);
436
437
LL_FOREACH(entries, e) {
438
blake2b_update (&st, e->key, strlen(e->key));
439
blake2b_update (&st, e->value, strlen(e->value));
440
}
441
*out = xmalloc(BLAKE2B_OUTBYTES);
442
blake2b_final (&st, *out, BLAKE2B_OUTBYTES);
443
*outlen = BLAKE2B_OUTBYTES;
444
}
445
446
static void
447
pkg_checksum_hash_blake2_bulk(const unsigned char *in, size_t inlen,
448
unsigned char **out, size_t *outlen)
449
{
450
*out = xmalloc(BLAKE2B_OUTBYTES);
451
blake2b(*out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0);
452
*outlen = BLAKE2B_OUTBYTES;
453
}
454
455
static void
456
pkg_checksum_hash_blake2_file(int fd, unsigned char **out, size_t *outlen)
457
{
458
char buffer[8192];
459
ssize_t r;
460
461
blake2b_state st;
462
blake2b_init(&st, BLAKE2B_OUTBYTES);
463
464
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
465
blake2b_update(&st, buffer, r);
466
if (r < 0) {
467
pkg_emit_errno(__func__, "read failed");
468
free(*out);
469
*out = NULL;
470
return;
471
}
472
*out = xmalloc(BLAKE2B_OUTBYTES);
473
blake2b_final(&st, *out, BLAKE2B_OUTBYTES);
474
*outlen = BLAKE2B_OUTBYTES;
475
}
476
477
static void
478
pkg_checksum_hash_blake2s(struct kv *entries,
479
unsigned char **out, size_t *outlen)
480
{
481
blake2s_state st;
482
struct kv *e;
483
484
blake2s_init (&st, BLAKE2S_OUTBYTES);
485
486
LL_FOREACH(entries, e) {
487
blake2s_update (&st, e->key, strlen(e->key));
488
blake2s_update (&st, e->value, strlen(e->value));
489
}
490
*out = xmalloc(BLAKE2S_OUTBYTES);
491
blake2s_final (&st, *out, BLAKE2S_OUTBYTES);
492
*outlen = BLAKE2S_OUTBYTES;
493
}
494
495
static void
496
pkg_checksum_hash_blake2s_bulk(const unsigned char *in, size_t inlen,
497
unsigned char **out, size_t *outlen)
498
{
499
*out = xmalloc(BLAKE2S_OUTBYTES);
500
blake2s(*out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0);
501
*outlen = BLAKE2S_OUTBYTES;
502
}
503
504
static void
505
pkg_checksum_hash_blake2s_file(int fd, unsigned char **out, size_t *outlen)
506
{
507
char buffer[8192];
508
ssize_t r;
509
510
blake2s_state st;
511
blake2s_init(&st, BLAKE2S_OUTBYTES);
512
513
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
514
blake2s_update(&st, buffer, r);
515
if (r < 0) {
516
pkg_emit_errno(__func__, "read failed");
517
free(*out);
518
*out = NULL;
519
return;
520
}
521
*out = xmalloc(BLAKE2S_OUTBYTES);
522
blake2s_final(&st, *out, BLAKE2S_OUTBYTES);
523
*outlen = BLAKE2S_OUTBYTES;
524
}
525
526
/*
527
* We use here z-base32 encoding described here:
528
* http://philzimmermann.com/docs/human-oriented-base-32-encoding.txt
529
*/
530
static const char b32[]="ybndrfg8ejkmcpqxot1uwisza345h769";
531
532
533
static void
534
pkg_checksum_encode_base32(unsigned char *in, size_t inlen,
535
char *out, size_t outlen)
536
{
537
int i, remain = -1, r, x;
538
539
if (outlen < inlen * 8 / 5) {
540
pkg_emit_error("cannot encode base32 as outlen is not sufficient");
541
return;
542
}
543
544
for (i = 0, r = 0; i < inlen; i++) {
545
switch (i % 5) {
546
case 0:
547
/* 8 bits of input and 3 to remain */
548
x = in[i];
549
remain = in[i] >> 5;
550
out[r++] = b32[x & 0x1F];
551
break;
552
case 1:
553
/* 11 bits of input, 1 to remain */
554
x = remain | in[i] << 3;
555
out[r++] = b32[x & 0x1F];
556
out[r++] = b32[x >> 5 & 0x1F];
557
remain = x >> 10;
558
break;
559
case 2:
560
/* 9 bits of input, 4 to remain */
561
x = remain | in[i] << 1;
562
out[r++] = b32[x & 0x1F];
563
remain = x >> 5;
564
break;
565
case 3:
566
/* 12 bits of input, 2 to remain */
567
x = remain | in[i] << 4;
568
out[r++] = b32[x & 0x1F];
569
out[r++] = b32[x >> 5 & 0x1F];
570
remain = x >> 10 & 0x3;
571
break;
572
case 4:
573
/* 10 bits of output, nothing to remain */
574
x = remain | in[i] << 2;
575
out[r++] = b32[x & 0x1F];
576
out[r++] = b32[x >> 5 & 0x1F];
577
remain = -1;
578
break;
579
default:
580
/* Not to be happen */
581
break;
582
}
583
584
}
585
if (remain >= 0)
586
out[r++] = b32[remain];
587
588
out[r] = 0;
589
}
590
591
static void
592
pkg_checksum_encode_hex(unsigned char *in, size_t inlen,
593
char *out, size_t outlen)
594
{
595
int i;
596
597
if (outlen < inlen * 2) {
598
pkg_emit_error("cannot encode hex as outlen is not sufficient");
599
return;
600
}
601
602
for (i = 0; i < inlen; i++)
603
sprintf(out + (i * 2), "%02x", in[i]);
604
605
out[inlen * 2] = '\0';
606
}
607
608
pkg_checksum_type_t
609
pkg_checksum_type_from_string(const char *name)
610
{
611
int i;
612
for (i = 0; i < PKG_HASH_TYPE_UNKNOWN; i ++) {
613
if (STRIEQ(name, checksum_types[i].name))
614
return (i);
615
}
616
617
return (PKG_HASH_TYPE_UNKNOWN);
618
}
619
620
const char*
621
pkg_checksum_type_to_string(pkg_checksum_type_t type)
622
{
623
return (checksum_types[type].name);
624
}
625
626
size_t
627
pkg_checksum_type_size(pkg_checksum_type_t type)
628
{
629
return (checksum_types[type].hlen);
630
}
631
632
int
633
pkg_checksum_calculate(struct pkg *pkg, struct pkgdb *db, bool inc_scripts,
634
bool inc_version, bool inc_files)
635
{
636
char *new_digest;
637
struct pkg_repo *repo;
638
int rc = EPKG_OK;
639
pkg_checksum_type_t type;
640
641
if (sizeof(void *) == 8)
642
type = PKG_HASH_TYPE_BLAKE2_BASE32;
643
else
644
type = PKG_HASH_TYPE_BLAKE2S_BASE32;
645
646
if (pkg->reponame != NULL) {
647
repo = pkg_repo_find(pkg->reponame);
648
649
if (repo != NULL)
650
type = repo->meta->digest_format;
651
}
652
653
new_digest = xmalloc(pkg_checksum_type_size(type));
654
if (pkg_checksum_generate(pkg, new_digest, pkg_checksum_type_size(type),
655
type, inc_scripts, inc_version, inc_files)
656
!= EPKG_OK) {
657
free(new_digest);
658
return (EPKG_FATAL);
659
}
660
661
free(pkg->digest);
662
pkg->digest = new_digest;
663
664
if (db != NULL)
665
pkgdb_set_pkg_digest(db, pkg);
666
667
return (rc);
668
}
669
670
671
unsigned char *
672
pkg_checksum_data(const unsigned char *in, size_t inlen,
673
pkg_checksum_type_t type)
674
{
675
const struct _pkg_cksum_type *cksum;
676
unsigned char *out, *res = NULL;
677
size_t outlen;
678
679
if (type >= PKG_HASH_TYPE_UNKNOWN || in == NULL)
680
return (NULL);
681
682
/* Zero terminated string */
683
if (inlen == 0) {
684
inlen = strlen(in);
685
}
686
687
cksum = &checksum_types[type];
688
689
cksum->hbulkfunc(in, inlen, &out, &outlen);
690
if (out != NULL) {
691
if (cksum->encfunc != NULL) {
692
res = xmalloc(cksum->hlen);
693
cksum->encfunc(out, outlen, res, cksum->hlen);
694
free(out);
695
}
696
else {
697
res = out;
698
}
699
}
700
701
return (res);
702
}
703
704
unsigned char *
705
pkg_checksum_fileat(int rootfd, const char *path, pkg_checksum_type_t type)
706
{
707
int fd;
708
unsigned char *ret;
709
710
if ((fd = openat(rootfd, path, O_RDONLY)) == -1) {
711
pkg_emit_errno("open", path);
712
return (NULL);
713
}
714
715
ret = pkg_checksum_fd(fd, type);
716
717
close(fd);
718
719
return (ret);
720
}
721
722
unsigned char *
723
pkg_checksum_file(const char *path, pkg_checksum_type_t type)
724
{
725
return pkg_checksum_fileat(AT_FDCWD, path, type);
726
}
727
728
unsigned char *
729
pkg_checksum_fd(int fd, pkg_checksum_type_t type)
730
{
731
const struct _pkg_cksum_type *cksum;
732
unsigned char *out, *res = NULL;
733
size_t outlen;
734
735
if (type >= PKG_HASH_TYPE_UNKNOWN || fd < 0)
736
return (NULL);
737
738
cksum = &checksum_types[type];
739
cksum->hfilefunc(fd, &out, &outlen);
740
if (out != NULL) {
741
if (cksum->encfunc != NULL) {
742
res = xmalloc(cksum->hlen);
743
cksum->encfunc(out, outlen, res, cksum->hlen);
744
free(out);
745
} else {
746
res = out;
747
}
748
}
749
750
return (res);
751
}
752
753
static unsigned char *
754
pkg_checksum_symlink_readlink(const char *linkbuf, int linklen,
755
pkg_checksum_type_t type)
756
{
757
const char *lnk;
758
759
lnk = linkbuf;
760
761
/*
762
* It is known that \0 is added to the checksum in case the symlink
763
* targets an absolute path but the behaviour is kept for compat
764
*/
765
return (pkg_checksum_data(RELATIVE_PATH(lnk), linklen, type));
766
}
767
768
unsigned char *
769
pkg_checksum_symlink(const char *path, pkg_checksum_type_t type)
770
{
771
return pkg_checksum_symlinkat(AT_FDCWD, path, type);
772
}
773
774
unsigned char *
775
pkg_checksum_symlinkat(int fd, const char *path, pkg_checksum_type_t type)
776
{
777
char linkbuf[MAXPATHLEN];
778
int linklen;
779
780
if ((linklen = readlinkat(fd, path, linkbuf, sizeof(linkbuf) - 1)) == -1) {
781
pkg_emit_errno("pkg_checksum_symlinkat", "readlink failed");
782
return (NULL);
783
}
784
linkbuf[linklen] = '\0';
785
786
return (pkg_checksum_symlink_readlink(linkbuf, linklen, type));
787
}
788
789
int
790
pkg_checksum_validate_file(const char *path, const char *sum)
791
{
792
return pkg_checksum_validate_fileat(AT_FDCWD, path, sum);
793
}
794
795
int
796
pkg_checksum_validate_fileat(int rootfd, const char *path, const char *sum)
797
{
798
struct stat st;
799
char *newsum;
800
pkg_checksum_type_t type;
801
802
type = pkg_checksum_file_get_type(sum, strlen(sum));
803
if (type == PKG_HASH_TYPE_UNKNOWN) {
804
type = PKG_HASH_TYPE_SHA256_HEX;
805
} else {
806
sum = strchr(sum, PKG_CKSUM_SEPARATOR);
807
if (sum != NULL)
808
sum++;
809
}
810
811
if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
812
return (errno);
813
}
814
815
if (S_ISLNK(st.st_mode))
816
newsum = pkg_checksum_symlinkat(rootfd, path, type);
817
else
818
newsum = pkg_checksum_fileat(rootfd, path, type);
819
820
if (newsum == NULL)
821
return (-1);
822
823
if (!STREQ(sum, newsum)) {
824
free(newsum);
825
return (-1);
826
}
827
828
free(newsum);
829
830
return (0);
831
}
832
833
char *
834
pkg_checksum_generate_file(const char *path, pkg_checksum_type_t type)
835
{
836
return pkg_checksum_generate_fileat(AT_FDCWD, path, type);
837
}
838
839
char *
840
pkg_checksum_generate_fileat(int rootfd, const char *path,
841
pkg_checksum_type_t type)
842
{
843
struct stat st;
844
unsigned char *sum;
845
char *cksum;
846
847
if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) == -1) {
848
pkg_emit_errno("pkg_checksum_generate_file", "lstat");
849
return (NULL);
850
}
851
852
if (S_ISLNK(st.st_mode))
853
sum = pkg_checksum_symlinkat(rootfd, path, type);
854
else
855
sum = pkg_checksum_fileat(rootfd, path, type);
856
857
if (sum == NULL)
858
return (NULL);
859
860
xasprintf(&cksum, "%d%c%s", type, PKG_CKSUM_SEPARATOR, sum);
861
free(sum);
862
863
return (cksum);
864
}
865
866