From 7de601a5b511b91d28bdc9902aea000b3e812074 Mon Sep 17 00:00:00 2001 From: Marcus Hoffmann Date: Mon, 14 Sep 2020 11:05:14 +0200 Subject: [PATCH] fallback to minsdk when targetsdk isn't set Androguard already has a function always returning an int here, so let's use that. Also put in a guard against minsdk not being set. --- fdroidserver/common.py | 17 +++++++++-- tests/common.TestCase | 37 +++++++++++++++++++++-- tests/no_targetsdk_minsdk1_unsigned.apk | Bin 0 -> 2266 bytes tests/no_targetsdk_minsdk30_unsigned.apk | Bin 0 -> 2310 bytes 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 tests/no_targetsdk_minsdk1_unsigned.apk create mode 100644 tests/no_targetsdk_minsdk30_unsigned.apk diff --git a/fdroidserver/common.py b/fdroidserver/common.py index 586867a6..2a59152a 100644 --- a/fdroidserver/common.py +++ b/fdroidserver/common.py @@ -3047,6 +3047,19 @@ def apk_extract_signatures(apkpath, outdir, manifest=True): out_file.write(in_apk.read(f.filename)) +def get_min_sdk_version(apk): + """ + This wraps the androguard function to always return and int and fall back to 1 + if we can't get a valid minsdk version + :param apk: androguard apk object + :return: minsdk as int + """ + try: + return int(apk.get_min_sdk_version()) + except TypeError: + return 1 + + def sign_apk(unsigned_path, signed_path, keyalias): """Sign and zipalign an unsigned APK, then save to a new file, deleting the unsigned @@ -3068,7 +3081,7 @@ def sign_apk(unsigned_path, signed_path, keyalias): """ apk = _get_androguard_APK(unsigned_path) - if int(apk.get_target_sdk_version()) >= 30: + if apk.get_effective_target_sdk_version() >= 30: if config['keystore'] == 'NONE': # NOTE: apksigner doesn't like -providerName/--provider-name at all, don't use # apksigner documents the options as --ks-provider-class and --ks-provider-arg @@ -3098,7 +3111,7 @@ def sign_apk(unsigned_path, signed_path, keyalias): os.remove(unsigned_path) else: - if int(apk.get_min_sdk_version()) < 18: + if get_min_sdk_version(apk) < 18: signature_algorithm = ['-sigalg', 'SHA1withRSA', '-digestalg', 'SHA1'] else: signature_algorithm = ['-sigalg', 'SHA256withRSA', '-digestalg', 'SHA-256'] diff --git a/tests/common.TestCase b/tests/common.TestCase index 98815d5b..ca06de8b 100755 --- a/tests/common.TestCase +++ b/tests/common.TestCase @@ -697,6 +697,37 @@ class CommonTest(unittest.TestCase): # verify it has a v2 signature self.assertTrue(fdroidserver.common._get_androguard_APK(signed).is_signed_v2()) + def test_sign_no_targetsdk(self): + fdroidserver.common.config = None + config = fdroidserver.common.read_config(fdroidserver.common.options) + if not fdroidserver.common.find_apksigner(): + self.skipTest('SKIPPING as apksigner is not installed!') + config['jarsigner'] = fdroidserver.common.find_sdk_tools_cmd('jarsigner') + config['keyalias'] = 'sova' + config['keystorepass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' + config['keypass'] = 'r9aquRHYoI8+dYz6jKrLntQ5/NJNASFBacJh7Jv2BlI=' + config['keystore'] = os.path.join(self.basedir, 'keystore.jks') + testdir = tempfile.mkdtemp(prefix=inspect.currentframe().f_code.co_name, dir=self.tmpdir) + + shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk30_unsigned.apk'), testdir) + unsigned = os.path.join(testdir, 'no_targetsdk_minsdk30_unsigned.apk') + signed = os.path.join(testdir, 'no_targetsdk_minsdk30_signed.apk') + + fdroidserver.common.sign_apk(unsigned, signed, config['keyalias']) + self.assertTrue(fdroidserver.common.verify_apk_signature(signed)) + self.assertTrue(fdroidserver.common._get_androguard_APK(signed).is_signed_v2()) + + shutil.copy(os.path.join(self.basedir, 'no_targetsdk_minsdk1_unsigned.apk'), testdir) + unsigned = os.path.join(testdir, 'no_targetsdk_minsdk1_unsigned.apk') + signed = os.path.join(testdir, 'no_targetsdk_minsdk1_signed.apk') + + self.assertFalse(fdroidserver.common.verify_apk_signature(unsigned)) + fdroidserver.common.sign_apk(unsigned, signed, config['keyalias']) + + self.assertTrue(os.path.isfile(signed)) + self.assertFalse(os.path.isfile(unsigned)) + self.assertTrue(fdroidserver.common.verify_apk_signature(signed)) + def test_get_apk_id(self): config = dict() fdroidserver.common.fill_config_defaults(config) @@ -796,11 +827,11 @@ class CommonTest(unittest.TestCase): """This is a sanity test that androguard isn't broken""" def get_minSdkVersion(apkfile): apk = fdroidserver.common._get_androguard_APK(apkfile) - return int(apk.get_min_sdk_version()) + return fdroidserver.common.get_min_sdk_version(apk) def get_targetSdkVersion(apkfile): apk = fdroidserver.common._get_androguard_APK(apkfile) - return int(apk.get_target_sdk_version()) + return apk.get_effective_target_sdk_version() self.assertEqual(4, get_minSdkVersion('bad-unicode-πÇÇ现代通用字-български-عربي1.apk')) self.assertEqual(14, get_minSdkVersion('org.bitbucket.tickytacky.mirrormirror_1.apk')) @@ -826,6 +857,8 @@ class CommonTest(unittest.TestCase): self.assertEqual(4, get_minSdkVersion('repo/urzip-; Рахма́, [rɐxˈmanʲɪnəf] سيرجي_رخمانينوف 谢·.apk')) self.assertEqual(30, get_targetSdkVersion('minimal_targetsdk_30_unsigned.apk')) + self.assertEqual(1, get_targetSdkVersion('no_targetsdk_minsdk1_unsigned.apk')) + self.assertEqual(30, get_targetSdkVersion('no_targetsdk_minsdk30_unsigned.apk')) def test_apk_release_name(self): appid, vercode, sigfp = fdroidserver.common.apk_parse_release_filename('com.serwylo.lexica_905.apk') diff --git a/tests/no_targetsdk_minsdk1_unsigned.apk b/tests/no_targetsdk_minsdk1_unsigned.apk new file mode 100644 index 0000000000000000000000000000000000000000..225e52bca567fadcc3e4a32b3a7a57092bc27a87 GIT binary patch literal 2266 zcmWIWW@cdk0uB(tz{_Q@XCWg4g9%Vf7|3_bODW3FOz}<3%S=lxF43#V&6yfx?RVHg zWKQqr!hI@2tQ{PI${rmqjT(-NmN0ZmO-@KsEmOLE!Ku-L>G=bODk4hg6B^B;yB@Rf-&^Yk{Qnb_)h#eClh=*bf(y^lo+3x zl9Oky-}9?|)eE!yWw{I5`O0>jF1((sWB7dIsr0pnHReW!%niEwP*&{F&AGEBK8YA@ z@7J5(@KdogHjMR(uXgE{!|N_d8~$3ud&RPL@k$Y!c{!nit9JTD6uOF9FMg?UJ-F=4 z%B+oU`)+m>>D;}w>he*>bysuPxR-sJKkvtV!$?7m>9UjVDySdL}{hSA3Zh+OV~etuK7KoE``Ce zk!9zbhtEGZ@-R(La{d+g`5Je@Z-w}3jy;=&-l^a5`?1gWw?cn&S!b74<;S=G?*F)R z)KS9IXY>AV{w+}GB+Gt(N}}Y|Yy*Q>jVHw~ zUmm@4=Z%*h^S>)Wdh;VA_k^EtQrMb0qw3bSYdwp0IcAGI@iE(4!tKE~Wsl$4SsNvn zPfHEYyt-j+#kEU5w++`M-CEK&xn=Y5BTsa?LwEfDWB5-pEb1vEk8@LH`TZT9Ym;j7 zN}DsU*5`6x<$5>0W#XP#&12WUbmhJ%JlnB7bzVzBdvV>BhnLx`Z9NrEU)VlpZhXOi z_bR=~xxH!2(>FQ1bJo9V^31~AH>za8>}jX9#dHlPNZqfC3HT}&V#>Tr>rBd(#0Q_Z zvFvm^tIJltZM$*j@vgM#r`m2>RIW*R?K3mv2TQ6?uB9=)DpQs#2ncbOb2k+Pb@8+xYVuH8?zzLeY_+1(toQHw zN)&d9D!I2jx4yLSMc9mvTN5?f{aT%#s|YbITKsipxbwT%pKXEmF6-~rFFa$?J=MOo zuaIHZ*4vZL&Qsd*RdnOp?H(6i=^JgS>fw*7ZF8}``_?o`_`OSN!_RhO|p5}#zsvpRMvIQ{xLjlJIt}-29wg6#11~!JG)Z+Zo zqGVvkNGvK&HoeKjz{0@9zyp>C7Rn5a3^EKFU>a%wP*4HN1W`;($(dj-lLF%ppj;OGyu~e9t0@B7(kkhp_rir z7+RSOdBCuPsMi70P(?tq6rfBH#lewSP!OM&n41cU0|9V33$hMoB_mS^Lk5%&5{m$0 z2Oy>tKuUOUNzV*2E5Mr(n36yMB7^d xO+YXC5hjEKor+WsAlwd7f|@rF+87w}fRzYpP6_a4Wdo^T0m2_Z`V2dW2LRS`#+m>C literal 0 HcmV?d00001 diff --git a/tests/no_targetsdk_minsdk30_unsigned.apk b/tests/no_targetsdk_minsdk30_unsigned.apk new file mode 100644 index 0000000000000000000000000000000000000000..ae8e86b530d36c4fdfcdf6332f0dcf6a4c6eea9b GIT binary patch literal 2310 zcmWIWW@cdk0uB(tQ0cVu(pg3Zh7zEdFp%$vh$=LQPaJPqQ;yA|2IJm%5ixu3`BD)e3&QX6_HN ze;BmY?lM1r!2E+{Uz7KS-g56`*_RRPXDlsEmC9Q5{E6gC);B(uXC&ubxj0+(Swpq_ zv-2m6ZH)VKitNK3-+0(Q6VMD`{j2!dFuiHj@tr=wGYlv0f4=`O|Ef*PPQK?7dYkFq zA7L8t)^K~LZ@}3Le0vwm&d|I*qgFr6;(TTN@;6*b{##B@6}CTW?mYGJ?l)V6weOVf z7yQhV`|kJCo|V={+nsxGOJ{Nob>r!^>**e z_={8jTW+ps*X+8px`xB){L=DiSMU2fvSf+u&M?<<^CIoy-q)8T?thRwzw_&f*!6RH zU+1-Izpj<}Jnd`Vv8uH}>#y#a^yAOh;)CxeRBk;K-(A<+HD9bQ;`Z$Wrs8w{i=C1w zUBBeo?@hRsgZ*3~+9=KSU$gDb`lo)&4HJ)?QCbk&xi0{^q#x?Vb-z88I0T`4W$ zeE76T&x`f5#%C(=Gw~^V`{9y8fDAe1c(m?4KID z362kfay;y_?o~17y?>s~-&7uU=x@ty&imUl-#;(Bpq3gEa zzPw&o&?@cm_-HX_oKLH2=kn}Zv#bA|f9HH;V+B*qb>G`-?l$aO>7+Q{+h6zDv*%$& zk{|r_pMIJ-_2}GGk7zbm+VNC0+H`G}eD&V0LEvloNk-QJLr5_`3#MZtdUJ z8YTMO+fn6xi1({maiu=7SADkXeimu*v*?~4Yq$3Q5_Q%T$*O6akFtKVzw~)#PPU1; z>1@_d47*k?lU!GQdy%TRRp!!7NtZV<20gyr&3$Yy>*HCRvZ05KR%ADvzb*8{YU?(h z9osig_OuH#Ssr7!_SnhfRCn_!o~`}?Zc|HN9otgse7j`(sdYv>-E^-@gq~U^yI3@M zri_1&R_Wqbk7DMOna=A_pL{A&qwK%`DC>fY55{rtH zO>eR?fXi?u1|F~yU;)m+$RNX@0j8m500kAGOc2Gyl$;6XGAS_r0Ls+^Ir$7l4CxGd z3~3B0Kvq6OCXm)+NCwg)11Nw34hRCEG>8ofM*}bo;z57{i~*$C7>XH6fT5MikOvGq zh~4{TKlx(VndKf;7& qpi`0R0fgHjN>H;0LK_3abYLZdnppz8S=m4;Sb*>ckp96A;sF5CbK-#j literal 0 HcmV?d00001