Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
apk-tools
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
59
Issues
59
List
Boards
Labels
Service Desk
Milestones
Merge Requests
14
Merge Requests
14
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
alpine
apk-tools
Commits
3f4f9e99
Commit
3f4f9e99
authored
Jul 17, 2009
by
Timo Teräs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
verify: new applet (ref
#46
)
an utility to check package signature and integrity.
parent
50fed106
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
259 additions
and
79 deletions
+259
-79
src/Makefile
src/Makefile
+1
-1
src/add.c
src/add.c
+4
-1
src/apk_package.h
src/apk_package.h
+29
-3
src/index.c
src/index.c
+4
-1
src/package.c
src/package.c
+172
-73
src/verify.c
src/verify.c
+49
-0
No files found.
src/Makefile
View file @
3f4f9e99
...
...
@@ -8,7 +8,7 @@ progs-y += apk
apk-objs
:=
state.o database.o package.o archive.o
\
version.o io.o url.o gunzip.o blob.o hash.o apk.o
\
add.o del.o update.o info.o search.o upgrade.o
\
cache.o ver.o index.o fetch.o audit.o
cache.o ver.o index.o fetch.o audit.o
verify.o
CFLAGS_apk.o
:=
-DAPK_VERSION
=
\"
$(FULL_VERSION)
\"
progs-$(STATIC)
+=
apk.static
...
...
src/add.c
View file @
3f4f9e99
...
...
@@ -117,8 +117,11 @@ static int add_main(void *ctx, int argc, char **argv)
if
(
strstr
(
argv
[
i
],
".apk"
)
!=
NULL
)
{
struct
apk_package
*
pkg
;
struct
apk_sign_ctx
sctx
;
pkg
=
apk_pkg_read
(
&
db
,
argv
[
i
],
APK_SIGN_VERIFY
);
apk_sign_ctx_init
(
&
sctx
,
APK_SIGN_VERIFY
);
pkg
=
apk_pkg_read
(
&
db
,
argv
[
i
],
&
sctx
);
apk_sign_ctx_free
(
&
sctx
);
if
(
pkg
==
NULL
)
{
apk_error
(
"Unable to read '%s'"
,
argv
[
i
]);
goto
err
;
...
...
src/apk_package.h
View file @
3f4f9e99
...
...
@@ -34,6 +34,25 @@ struct apk_name;
#define APK_SIGN_GENERATE_V1 1
#define APK_SIGN_GENERATE 2
struct
apk_sign_ctx
{
int
action
;
const
EVP_MD
*
md
;
int
num_signatures
;
int
control_started
:
1
;
int
data_started
:
1
;
int
has_data_checksum
:
1
;
int
control_verified
:
1
;
int
data_verified
:
1
;
char
data_checksum
[
EVP_MAX_MD_SIZE
];
struct
apk_checksum
identity
;
struct
{
apk_blob_t
data
;
EVP_PKEY
*
pkey
;
char
*
identity
;
}
signature
;
};
struct
apk_script
{
struct
hlist_node
script_list
;
unsigned
int
type
;
...
...
@@ -73,6 +92,13 @@ APK_ARRAY(apk_package_array, struct apk_package *);
extern
const
char
*
apk_script_types
[];
void
apk_sign_ctx_init
(
struct
apk_sign_ctx
*
ctx
,
int
action
);
void
apk_sign_ctx_free
(
struct
apk_sign_ctx
*
ctx
);
int
apk_sign_ctx_process_file
(
struct
apk_sign_ctx
*
ctx
,
const
struct
apk_file_info
*
fi
,
struct
apk_istream
*
is
);
int
apk_sign_ctx_mpart_cb
(
void
*
ctx
,
EVP_MD_CTX
*
mdctx
,
int
part
);
int
apk_deps_add
(
struct
apk_dependency_array
**
depends
,
struct
apk_dependency
*
dep
);
void
apk_deps_del
(
struct
apk_dependency_array
**
deps
,
...
...
@@ -84,7 +110,8 @@ int apk_deps_write(struct apk_dependency_array *deps, struct apk_ostream *os);
int
apk_script_type
(
const
char
*
name
);
struct
apk_package
*
apk_pkg_new
(
void
);
struct
apk_package
*
apk_pkg_read
(
struct
apk_database
*
db
,
const
char
*
name
,
int
indexstyle
);
struct
apk_package
*
apk_pkg_read
(
struct
apk_database
*
db
,
const
char
*
name
,
struct
apk_sign_ctx
*
ctx
);
void
apk_pkg_free
(
struct
apk_package
*
pkg
);
int
apk_pkg_parse_name
(
apk_blob_t
apkname
,
apk_blob_t
*
name
,
apk_blob_t
*
version
);
...
...
@@ -103,8 +130,7 @@ int apk_pkg_write_index_entry(struct apk_package *pkg, struct apk_ostream *os);
int
apk_pkg_version_compare
(
struct
apk_package
*
a
,
struct
apk_package
*
b
);
struct
apk_dependency
apk_dep_from_str
(
struct
apk_database
*
db
,
char
*
str
);
struct
apk_dependency
apk_dep_from_str
(
struct
apk_database
*
db
,
char
*
str
);
struct
apk_dependency
apk_dep_from_pkg
(
struct
apk_database
*
db
,
struct
apk_package
*
pkg
);
#endif
src/index.c
View file @
3f4f9e99
...
...
@@ -158,8 +158,11 @@ static int index_main(void *ctx, int argc, char **argv)
}
while
(
0
);
if
(
!
found
)
{
if
(
apk_pkg_read
(
&
db
,
argv
[
i
],
ictx
->
method
)
!=
NULL
)
struct
apk_sign_ctx
sctx
;
apk_sign_ctx_init
(
&
sctx
,
ictx
->
method
);
if
(
apk_pkg_read
(
&
db
,
argv
[
i
],
&
sctx
)
!=
NULL
)
newpkgs
++
;
apk_sign_ctx_free
(
&
sctx
);
}
}
...
...
src/package.c
View file @
3f4f9e99
...
...
@@ -20,6 +20,8 @@
#include <unistd.h>
#include <sys/wait.h>
#include <openssl/pem.h>
#include "apk_defines.h"
#include "apk_archive.h"
#include "apk_package.h"
...
...
@@ -254,16 +256,162 @@ int apk_script_type(const char *name)
return
APK_SCRIPT_INVALID
;
}
void
apk_sign_ctx_init
(
struct
apk_sign_ctx
*
ctx
,
int
action
)
{
memset
(
ctx
,
0
,
sizeof
(
struct
apk_sign_ctx
));
switch
(
ctx
->
action
)
{
case
APK_SIGN_VERIFY
:
ctx
->
md
=
EVP_md_null
();
break
;
case
APK_SIGN_GENERATE_V1
:
ctx
->
md
=
EVP_md5
();
break
;
case
APK_SIGN_GENERATE
:
default:
action
=
APK_SIGN_GENERATE
;
ctx
->
md
=
EVP_sha1
();
break
;
}
ctx
->
action
=
action
;
}
void
apk_sign_ctx_free
(
struct
apk_sign_ctx
*
ctx
)
{
if
(
ctx
->
signature
.
data
.
ptr
!=
NULL
)
free
(
ctx
->
signature
.
data
.
ptr
);
if
(
ctx
->
signature
.
pkey
!=
NULL
)
EVP_PKEY_free
(
ctx
->
signature
.
pkey
);
}
int
apk_sign_ctx_process_file
(
struct
apk_sign_ctx
*
ctx
,
const
struct
apk_file_info
*
fi
,
struct
apk_istream
*
is
)
{
if
(
ctx
->
data_started
)
return
1
;
if
(
fi
->
name
[
0
]
!=
'.'
)
{
ctx
->
data_started
=
1
;
ctx
->
control_started
=
1
;
return
1
;
}
if
(
ctx
->
control_started
)
return
1
;
if
(
strncmp
(
fi
->
name
,
".SIGN."
,
6
)
!=
0
)
{
ctx
->
control_started
=
1
;
return
1
;
}
/* A signature file */
ctx
->
num_signatures
++
;
/* Found already a trusted key */
if
(
ctx
->
signature
.
pkey
!=
NULL
)
return
0
;
if
(
strncmp
(
&
fi
->
name
[
6
],
"RSA."
,
4
)
==
0
||
strncmp
(
&
fi
->
name
[
6
],
"DSA."
,
4
)
==
0
)
{
char
file
[
256
];
BIO
*
bio
=
BIO_new
(
BIO_s_file
());
snprintf
(
file
,
sizeof
(
file
),
"/etc/apk/keys/%s"
,
&
fi
->
name
[
10
]);
if
(
BIO_read_filename
(
bio
,
file
)
>
0
)
ctx
->
signature
.
pkey
=
PEM_read_bio_PUBKEY
(
bio
,
NULL
,
NULL
,
NULL
);
if
(
ctx
->
signature
.
pkey
!=
NULL
)
{
if
(
fi
->
name
[
6
]
==
'R'
)
ctx
->
md
=
EVP_sha1
();
else
ctx
->
md
=
EVP_dss1
();
}
BIO_free
(
bio
);
}
else
return
0
;
if
(
ctx
->
signature
.
pkey
!=
NULL
)
ctx
->
signature
.
data
=
apk_blob_from_istream
(
is
,
fi
->
size
);
return
0
;
}
int
apk_sign_ctx_mpart_cb
(
void
*
ctx
,
EVP_MD_CTX
*
mdctx
,
int
part
)
{
struct
apk_sign_ctx
*
sctx
=
(
struct
apk_sign_ctx
*
)
ctx
;
unsigned
char
calculated
[
EVP_MAX_MD_SIZE
];
int
r
;
switch
(
part
)
{
case
APK_MPART_BEGIN
:
EVP_DigestInit_ex
(
mdctx
,
sctx
->
md
,
NULL
);
break
;
case
APK_MPART_BOUNDARY
:
/* We are not interested about checksums of signature,
* reset checksum if we are still in signatures */
if
(
!
sctx
->
control_started
)
{
EVP_DigestFinal_ex
(
mdctx
,
calculated
,
NULL
);
EVP_DigestInit_ex
(
mdctx
,
sctx
->
md
,
NULL
);
return
0
;
}
/* Are we in control part?. */
if
((
!
sctx
->
control_started
)
||
sctx
->
data_started
)
return
0
;
/* End of control block, make sure rest is handled as data */
sctx
->
data_started
=
1
;
/* Verify the signature if we have public key */
if
(
sctx
->
action
==
APK_SIGN_VERIFY
&&
sctx
->
signature
.
pkey
!=
NULL
)
{
r
=
EVP_VerifyFinal
(
mdctx
,
(
unsigned
char
*
)
sctx
->
signature
.
data
.
ptr
,
sctx
->
signature
.
data
.
len
,
sctx
->
signature
.
pkey
);
if
(
r
!=
1
)
return
1
;
sctx
->
control_verified
=
1
;
EVP_DigestInit_ex
(
mdctx
,
sctx
->
md
,
NULL
);
return
0
;
}
else
if
(
sctx
->
action
==
APK_SIGN_GENERATE
&&
sctx
->
has_data_checksum
)
{
/* Package identity is checksum of control block */
sctx
->
identity
.
type
=
EVP_MD_CTX_size
(
mdctx
);
EVP_DigestFinal_ex
(
mdctx
,
sctx
->
identity
.
data
,
NULL
);
return
1
;
}
else
{
/* Reset digest for hashing data */
EVP_DigestFinal_ex
(
mdctx
,
calculated
,
NULL
);
EVP_DigestInit_ex
(
mdctx
,
sctx
->
md
,
NULL
);
}
break
;
case
APK_MPART_END
:
if
(
sctx
->
action
==
APK_SIGN_VERIFY
)
{
/* Check that data checksum matches */
EVP_DigestFinal_ex
(
mdctx
,
calculated
,
NULL
);
if
(
sctx
->
has_data_checksum
&&
EVP_MD_CTX_size
(
mdctx
)
!=
0
&&
memcmp
(
calculated
,
sctx
->
data_checksum
,
EVP_MD_CTX_size
(
mdctx
))
==
0
)
sctx
->
data_verified
=
1
;
}
else
{
/* Package identity is checksum of all data */
sctx
->
identity
.
type
=
EVP_MD_CTX_size
(
mdctx
);
EVP_DigestFinal_ex
(
mdctx
,
sctx
->
identity
.
data
,
NULL
);
}
return
1
;
}
return
0
;
}
struct
read_info_ctx
{
struct
apk_database
*
db
;
struct
apk_package
*
pkg
;
const
EVP_MD
*
md
;
int
version
,
action
;
int
has_signature
:
1
;
struct
apk_sign_ctx
*
sctx
;
int
version
;
int
has_install
:
1
;
int
has_data_checksum
:
1
;
int
data_started
:
1
;
int
in_signatures
:
1
;
};
int
apk_pkg_add_info
(
struct
apk_database
*
db
,
struct
apk_package
*
pkg
,
...
...
@@ -336,9 +484,14 @@ static int read_info_line(void *ctx, apk_blob_t line)
}
}
if
(
ri
->
data_started
==
0
&&
apk_blob_compare
(
APK_BLOB_STR
(
"datahash"
),
l
)
==
0
)
ri
->
has_data_checksum
=
1
;
if
(
ri
->
sctx
->
data_started
==
0
&&
apk_blob_compare
(
APK_BLOB_STR
(
"datahash"
),
l
)
==
0
)
{
ri
->
sctx
->
has_data_checksum
=
1
;
ri
->
sctx
->
md
=
EVP_sha256
();
apk_blob_pull_hexdump
(
&
r
,
APK_BLOB_PTR_LEN
(
ri
->
sctx
->
data_checksum
,
EVP_MD_size
(
ri
->
sctx
->
md
)));
}
return
0
;
}
...
...
@@ -363,18 +516,16 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
int
i
;
/* Meta info and scripts */
if
(
ri
->
in_signatures
&&
strncmp
(
ae
->
name
,
".SIGN."
,
6
)
!
=
0
)
r
i
->
in_signatures
=
0
;
if
(
apk_sign_ctx_process_file
(
ri
->
sctx
,
ae
,
is
)
=
=
0
)
r
eturn
0
;
if
(
ri
->
data_started
==
0
&&
ae
->
name
[
0
]
==
'.'
)
{
if
(
ri
->
sctx
->
data_started
==
0
&&
ae
->
name
[
0
]
==
'.'
)
{
/* APK 2.0 format */
if
(
strcmp
(
ae
->
name
,
".PKGINFO"
)
==
0
)
{
apk_blob_t
blob
=
apk_blob_from_istream
(
is
,
ae
->
size
);
apk_blob_for_each_segment
(
blob
,
"
\n
"
,
read_info_line
,
ctx
);
free
(
blob
.
ptr
);
ri
->
version
=
2
;
}
else
if
(
strncmp
(
ae
->
name
,
".SIGN."
,
6
)
==
0
)
{
ri
->
has_signature
=
1
;
}
else
if
(
strcmp
(
ae
->
name
,
".INSTALL"
)
==
0
)
{
apk_warning
(
"Package '%s-%s' contains deprecated .INSTALL"
,
pkg
->
name
->
name
,
pkg
->
version
);
...
...
@@ -382,7 +533,6 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
return
0
;
}
ri
->
data_started
=
1
;
if
(
strncmp
(
ae
->
name
,
"var/db/apk/"
,
11
)
==
0
)
{
/* APK 1.0 format */
ri
->
version
=
1
;
...
...
@@ -423,35 +573,8 @@ static int read_info_entry(void *ctx, const struct apk_file_info *ae,
return
0
;
}
static
int
apk_pkg_gzip_part
(
void
*
ctx
,
EVP_MD_CTX
*
mdctx
,
int
part
)
{
struct
read_info_ctx
*
ri
=
(
struct
read_info_ctx
*
)
ctx
;
switch
(
part
)
{
case
APK_MPART_BEGIN
:
EVP_DigestInit_ex
(
mdctx
,
ri
->
md
,
NULL
);
break
;
case
APK_MPART_BOUNDARY
:
if
(
ri
->
in_signatures
)
{
EVP_DigestFinal_ex
(
mdctx
,
ri
->
pkg
->
csum
.
data
,
NULL
);
EVP_DigestInit_ex
(
mdctx
,
ri
->
md
,
NULL
);
return
0
;
}
if
(
ri
->
action
==
APK_SIGN_GENERATE_V1
||
!
ri
->
has_data_checksum
)
break
;
/* Fallthrough to calculate checksum */
case
APK_MPART_END
:
ri
->
pkg
->
csum
.
type
=
EVP_MD_CTX_size
(
mdctx
);
EVP_DigestFinal_ex
(
mdctx
,
ri
->
pkg
->
csum
.
data
,
NULL
);
return
1
;
}
return
0
;
}
struct
apk_package
*
apk_pkg_read
(
struct
apk_database
*
db
,
const
char
*
file
,
int
action
)
struct
apk_sign_ctx
*
sctx
)
{
struct
read_info_ctx
ctx
;
struct
apk_file_info
fi
;
...
...
@@ -466,22 +589,7 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file,
return
NULL
;
memset
(
&
ctx
,
0
,
sizeof
(
ctx
));
switch
(
action
)
{
case
APK_SIGN_VERIFY
:
ctx
.
in_signatures
=
1
;
ctx
.
md
=
EVP_md_null
();
break
;
case
APK_SIGN_GENERATE
:
ctx
.
in_signatures
=
1
;
ctx
.
md
=
EVP_sha1
();
break
;
case
APK_SIGN_GENERATE_V1
:
ctx
.
md
=
EVP_md5
();
break
;
default:
return
NULL
;
}
ctx
.
sctx
=
sctx
;
ctx
.
pkg
=
apk_pkg_new
();
if
(
ctx
.
pkg
==
NULL
)
return
NULL
;
...
...
@@ -492,27 +600,18 @@ struct apk_package *apk_pkg_read(struct apk_database *db, const char *file,
ctx
.
db
=
db
;
ctx
.
has_install
=
0
;
ctx
.
action
=
action
;
ctx
.
pkg
->
size
=
fi
.
size
;
tar
=
apk_bstream_gunzip_mpart
(
bs
,
apk_
pkg_gzip_part
,
&
ctx
);
tar
=
apk_bstream_gunzip_mpart
(
bs
,
apk_
sign_ctx_mpart_cb
,
s
ctx
);
r
=
apk_tar_parse
(
tar
,
read_info_entry
,
&
ctx
);
tar
->
close
(
tar
);
switch
(
r
)
{
case
0
:
break
;
case
-
2
:
apk_error
(
"File %s does not have a signature"
,
file
);
if
(
r
<
0
)
goto
err
;
default:
apk_error
(
"File %s is not an APK archive"
,
file
);
if
(
ctx
.
pkg
->
name
==
NULL
)
goto
err
;
}
if
(
ctx
.
pkg
->
name
==
NULL
)
{
apk_error
(
"File %s is corrupted"
,
file
);
if
(
sctx
->
action
==
APK_SIGN_VERIFY
&&
!
sctx
->
data_verified
&&
!
(
apk_flags
&
APK_FORCE
))
goto
err
;
}
/* Add implicit busybox dependency if there is scripts */
if
(
ctx
.
has_install
)
{
...
...
src/verify.c
0 → 100644
View file @
3f4f9e99
/* verify.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2009 Timo Teräs <timo.teras@iki.fi>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. See http://www.gnu.org/ for details.
*/
#include <stdio.h>
#include <unistd.h>
#include "apk_applet.h"
#include "apk_database.h"
static
int
verify_main
(
void
*
ctx
,
int
argc
,
char
**
argv
)
{
struct
apk_database
db
;
struct
apk_sign_ctx
sctx
;
int
i
,
ok
,
rc
=
0
;
apk_db_open
(
&
db
,
NULL
,
APK_OPENF_NO_STATE
);
for
(
i
=
0
;
i
<
argc
;
i
++
)
{
apk_sign_ctx_init
(
&
sctx
,
APK_SIGN_VERIFY
);
apk_pkg_read
(
&
db
,
argv
[
i
],
&
sctx
);
ok
=
sctx
.
control_verified
&&
sctx
.
data_verified
;
if
(
apk_verbosity
>=
1
)
apk_message
(
"%s: %s"
,
argv
[
i
],
ok
?
"OK"
:
sctx
.
data_verified
?
"UNTRUSTED"
:
"FAILED"
);
if
(
!
ok
)
rc
++
;
apk_sign_ctx_free
(
&
sctx
);
}
apk_db_close
(
&
db
);
return
rc
;
}
static
struct
apk_applet
apk_verify
=
{
.
name
=
"verify"
,
.
help
=
"Verify package integrity and signature"
,
.
arguments
=
"FILE..."
,
.
main
=
verify_main
,
};
APK_DEFINE_APPLET
(
apk_verify
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment