diff options
36 files changed, 896 insertions, 316 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7aee501..b13cfc1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - name: install dependencies run: | sudo apt-get update - sudo apt-get install cython + sudo apt-get install cython3 - name: prepare environment run: | echo "target_triplet=`gcc -dumpmachine`" >> $GITHUB_ENV @@ -45,7 +45,7 @@ jobs: done sudo cp -r extract/* / sudo ldconfig - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 - name: autogen @@ -60,7 +60,7 @@ jobs: DESTDIR=`pwd`/dest make install tar -C dest -cf libimobiledevice.tar usr - name: publish artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: libimobiledevice-latest_${{env.target_triplet}} path: libimobiledevice.tar @@ -104,7 +104,7 @@ jobs: tar -C extract -xvf $I done sudo cp -r extract/* / - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install additional requirements run: | mkdir -p lib @@ -146,7 +146,7 @@ jobs: DESTDIR=`pwd`/dest make install tar -C dest -cf libimobiledevice.tar usr - name: publish artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: libimobiledevice-latest_macOS path: libimobiledevice.tar @@ -210,7 +210,7 @@ jobs: tar -C extract -xvf $I done cp -r extract/* / - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: autogen run: ./autogen.sh CC=gcc CXX=g++ --enable-debug - name: make @@ -223,7 +223,7 @@ jobs: DESTDIR=`pwd`/dest make install tar -C dest -cf libimobiledevice.tar ${{ env.dest }} - name: publish artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: libimobiledevice-latest_${{ matrix.arch }}-${{ env.dest }} path: libimobiledevice.tar diff --git a/3rd_party/ed25519/Makefile.am b/3rd_party/ed25519/Makefile.am index c475331..d8e4e04 100644 --- a/3rd_party/ed25519/Makefile.am +++ b/3rd_party/ed25519/Makefile.am @@ -6,7 +6,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(GLOBAL_CFLAGS) \ - $(openssl_CFLAGS) + $(ssl_lib_CFLAGS) AM_LDFLAGS = diff --git a/3rd_party/ed25519/seed.c b/3rd_party/ed25519/seed.c index 11a2e3e..cf252b8 100644 --- a/3rd_party/ed25519/seed.c +++ b/3rd_party/ed25519/seed.c @@ -30,7 +30,7 @@ int ed25519_create_seed(unsigned char *seed) { return 1; } - fread(seed, 1, 32, f); + if(fread(seed, 1, 32, f)){} fclose(f); #endif diff --git a/3rd_party/libsrp6a-sha512/Makefile.am b/3rd_party/libsrp6a-sha512/Makefile.am index d304585..2acd582 100644 --- a/3rd_party/libsrp6a-sha512/Makefile.am +++ b/3rd_party/libsrp6a-sha512/Makefile.am @@ -5,8 +5,6 @@ AM_CPPFLAGS = \ -I$(top_srcdir) \ -Wno-incompatible-pointer-types -include_HEADERS = srp.h srp_aux.h cstr.h - AM_CFLAGS = -DHAVE_CONFIG_H if HAVE_OPENSSL AM_CFLAGS += -DOPENSSL=1 $(openssl_CFLAGS) @@ -25,7 +23,9 @@ noinst_LTLIBRARIES = libsrp6a-sha512.la libsrp6a_sha512_la_SOURCES = \ t_conv.c t_math.c t_misc.c \ t_truerand.c cstr.c \ - srp.c srp6a_sha512_client.c -if !HAVE_OPENSSL -libsrp6a_sha512_la_SOURCES += t_sha.c -endif + srp.c srp6a_sha512_client.c \ + srp.h srp_aux.h cstr.h \ + t_sha.c +#if !HAVE_OPENSSL +#libsrp6a_sha512_la_SOURCES += t_sha.c +#endif diff --git a/3rd_party/libsrp6a-sha512/t_conv.c b/3rd_party/libsrp6a-sha512/t_conv.c index f7f50e2..76d4e58 100644 --- a/3rd_party/libsrp6a-sha512/t_conv.c +++ b/3rd_party/libsrp6a-sha512/t_conv.c @@ -33,8 +33,7 @@ #include "cstr.h" static int -hexDigitToInt(c) - char c; +hexDigitToInt(char c) { if(c >= '0' && c <= '9') return c - '0'; @@ -50,9 +49,7 @@ hexDigitToInt(c) * Convert a hex string to a string of bytes; return size of dst */ _TYPE( int ) -t_fromhex(dst, src) - char * dst; - const char * src; +t_fromhex(char *dst, const char *src) { register char *chp = dst; register unsigned size = strlen(src); @@ -76,10 +73,7 @@ t_fromhex(dst, src) * Convert a string of bytes to their hex representation */ _TYPE( char * ) -t_tohex(dst, src, size) - char * dst; - const char * src; - unsigned size; +t_tohex(char *dst, const char *src, unsigned size) { int notleading = 0; @@ -103,10 +97,7 @@ t_tohex(dst, src, size) } _TYPE( char * ) -t_tohexcstr(dst, src, size) - cstr * dst; - const char * src; - unsigned size; +t_tohexcstr(cstr *dst, const char *src, unsigned size) { cstr_set_length(dst, 2 * size + 1); return t_tohex(dst->data, src, size); @@ -119,9 +110,7 @@ static char b64table[] = * Convert a base64 string into raw byte array representation. */ _TYPE( int ) -t_fromb64(dst, src) - char * dst; - const char * src; +t_fromb64(char *dst, const char *src) { unsigned char *a; char *loc; @@ -179,9 +168,7 @@ t_fromb64(dst, src) } _TYPE( int ) -t_cstrfromb64(dst, src) - cstr * dst; - const char * src; +t_cstrfromb64(cstr *dst, const char *src) { int len; cstr_set_length(dst, (strlen(src) * 6 + 7) / 8); @@ -194,10 +181,7 @@ t_cstrfromb64(dst, src) * Convert a raw byte string into a null-terminated base64 ASCII string. */ _TYPE( char * ) -t_tob64(dst, src, size) - char * dst; - const char * src; - unsigned size; +t_tob64(char *dst, const char *src, unsigned size) { int c, pos = size % 3; unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0; @@ -248,10 +232,7 @@ t_tob64(dst, src, size) } _TYPE( char * ) -t_tob64cstr(dst, src, sz) - cstr * dst; - const char * src; - unsigned int sz; +t_tob64cstr(cstr *dst, const char *src, unsigned int sz) { cstr_set_length(dst, (sz * 8 + 5) / 6 + 1); return t_tob64(dst->data, src, sz); diff --git a/3rd_party/libsrp6a-sha512/t_math.c b/3rd_party/libsrp6a-sha512/t_math.c index e655daa..037650e 100644 --- a/3rd_party/libsrp6a-sha512/t_math.c +++ b/3rd_party/libsrp6a-sha512/t_math.c @@ -39,11 +39,13 @@ typedef BIGNUM * BigInteger; typedef BN_CTX * BigIntegerCtx; typedef BN_MONT_CTX * BigIntegerModAccel; #include <limits.h> +#if OPENSSL_VERSION_NUMBER < 0x30000000L # ifndef OPENSSL_NO_ENGINE # define OPENSSL_ENGINE # include "openssl/engine.h" static ENGINE * default_engine = NULL; # endif /* OPENSSL_ENGINE */ +#endif typedef int (*modexp_meth)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx); static modexp_meth default_modexp = NULL; @@ -99,8 +101,7 @@ typedef void * BigIntegerModAccel; /* Math library interface stubs */ BigInteger -BigIntegerFromInt(n) - unsigned int n; +BigIntegerFromInt(unsigned int n) { #ifdef OPENSSL BIGNUM * a = BN_new(); @@ -136,9 +137,7 @@ BigIntegerFromInt(n) } BigInteger -BigIntegerFromBytes(bytes, length) - const unsigned char * bytes; - int length; +BigIntegerFromBytes(const unsigned char *bytes, int length) { #ifdef OPENSSL BIGNUM * a = BN_new(); @@ -206,10 +205,7 @@ BigIntegerFromBytes(bytes, length) } int -BigIntegerToBytes(src, dest, destlen) - BigInteger src; - unsigned char * dest; - int destlen; +BigIntegerToBytes(BigInteger src, unsigned char *dest, int destlen) { #ifdef OPENSSL return BN_bn2bin(src, dest); @@ -290,10 +286,7 @@ BigIntegerToCstrEx(BigInteger x, cstr * out, int len) } BigIntegerResult -BigIntegerToHex(src, dest, destlen) - BigInteger src; - char * dest; - int destlen; +BigIntegerToHex(BigInteger src, char *dest, int destlen) { #ifdef OPENSSL strncpy(dest, BN_bn2hex(src), destlen); @@ -317,11 +310,7 @@ static char b64table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./"; BigIntegerResult -BigIntegerToString(src, dest, destlen, radix) - BigInteger src; - char * dest; - int destlen; - unsigned int radix; +BigIntegerToString(BigInteger src, char *dest, int destlen, unsigned int radix) { BigInteger t = BigIntegerFromInt(0); char * p = dest; @@ -345,8 +334,7 @@ BigIntegerToString(src, dest, destlen, radix) } int -BigIntegerBitLen(b) - BigInteger b; +BigIntegerBitLen(BigInteger b) { #ifdef OPENSSL return BN_num_bits(b); @@ -364,8 +352,7 @@ BigIntegerBitLen(b) } int -BigIntegerCmp(c1, c2) - BigInteger c1, c2; +BigIntegerCmp(BigInteger c1, BigInteger c2) { #ifdef OPENSSL return BN_cmp(c1, c2); @@ -383,9 +370,7 @@ BigIntegerCmp(c1, c2) } int -BigIntegerCmpInt(c1, c2) - BigInteger c1; - unsigned int c2; +BigIntegerCmpInt(BigInteger c1, unsigned int c2) { #ifdef OPENSSL BigInteger bc2 = BigIntegerFromInt(c2); @@ -414,9 +399,7 @@ BigIntegerCmpInt(c1, c2) } BigIntegerResult -BigIntegerLShift(result, x, bits) - BigInteger result, x; - unsigned int bits; +BigIntegerLShift(BigInteger result, BigInteger x, unsigned int bits) { #ifdef OPENSSL BN_lshift(result, x, bits); @@ -436,8 +419,7 @@ BigIntegerLShift(result, x, bits) } BigIntegerResult -BigIntegerAdd(result, a1, a2) - BigInteger result, a1, a2; +BigIntegerAdd(BigInteger result, BigInteger a1, BigInteger a2) { #ifdef OPENSSL BN_add(result, a1, a2); @@ -456,9 +438,7 @@ BigIntegerAdd(result, a1, a2) } BigIntegerResult -BigIntegerAddInt(result, a1, a2) - BigInteger result, a1; - unsigned int a2; +BigIntegerAddInt(BigInteger result, BigInteger a1, unsigned int a2) { #ifdef OPENSSL if(result != a1) @@ -483,8 +463,7 @@ BigIntegerAddInt(result, a1, a2) } BigIntegerResult -BigIntegerSub(result, s1, s2) - BigInteger result, s1, s2; +BigIntegerSub(BigInteger result, BigInteger s1, BigInteger s2) { #ifdef OPENSSL BN_sub(result, s1, s2); @@ -503,9 +482,7 @@ BigIntegerSub(result, s1, s2) } BigIntegerResult -BigIntegerSubInt(result, s1, s2) - BigInteger result, s1; - unsigned int s2; +BigIntegerSubInt(BigInteger result, BigInteger s1, unsigned int s2) { #ifdef OPENSSL if(result != s1) @@ -530,9 +507,7 @@ BigIntegerSubInt(result, s1, s2) } BigIntegerResult -BigIntegerMul(result, m1, m2, c) - BigInteger result, m1, m2; - BigIntegerCtx c; +BigIntegerMul(BigInteger result, BigInteger m1, BigInteger m2, BigIntegerCtx c) { #ifdef OPENSSL BN_CTX * ctx = NULL; @@ -556,10 +531,7 @@ BigIntegerMul(result, m1, m2, c) } BigIntegerResult -BigIntegerMulInt(result, m1, m2, c) - BigInteger result, m1; - unsigned int m2; - BigIntegerCtx c; +BigIntegerMulInt(BigInteger result, BigInteger m1, unsigned int m2, BigIntegerCtx c) { #ifdef OPENSSL if(result != m1) @@ -584,10 +556,7 @@ BigIntegerMulInt(result, m1, m2, c) } BigIntegerResult -BigIntegerDivInt(result, d, m, c) - BigInteger result, d; - unsigned int m; - BigIntegerCtx c; +BigIntegerDivInt(BigInteger result, BigInteger d, unsigned int m, BigIntegerCtx c) { #ifdef OPENSSL if(result != d) @@ -624,9 +593,7 @@ BigIntegerDivInt(result, d, m, c) } BigIntegerResult -BigIntegerMod(result, d, m, c) - BigInteger result, d, m; - BigIntegerCtx c; +BigIntegerMod(BigInteger result, BigInteger d, BigInteger m, BigIntegerCtx c) { #ifdef OPENSSL BN_CTX * ctx = NULL; @@ -650,10 +617,7 @@ BigIntegerMod(result, d, m, c) } unsigned int -BigIntegerModInt(d, m, c) - BigInteger d; - unsigned int m; - BigIntegerCtx c; +BigIntegerModInt(BigInteger d, unsigned int m, BigIntegerCtx c) { #ifdef OPENSSL return BN_mod_word(d, m); @@ -711,9 +675,7 @@ BigIntegerModInt(d, m, c) } BigIntegerResult -BigIntegerModMul(r, m1, m2, modulus, c) - BigInteger r, m1, m2, modulus; - BigIntegerCtx c; +BigIntegerModMul(BigInteger r, BigInteger m1, BigInteger m2, BigInteger modulus, BigIntegerCtx c) { #ifdef OPENSSL BN_CTX * ctx = NULL; @@ -743,10 +705,7 @@ BigIntegerModMul(r, m1, m2, modulus, c) } BigIntegerResult -BigIntegerModExp(r, b, e, m, c, a) - BigInteger r, b, e, m; - BigIntegerCtx c; - BigIntegerModAccel a; +BigIntegerModExp(BigInteger r, BigInteger b, BigInteger e, BigInteger m, BigIntegerCtx c, BigIntegerModAccel a) { #ifdef OPENSSL #if OPENSSL_VERSION_NUMBER >= 0x00906000 @@ -793,9 +752,7 @@ int _mbedtls_f_rng(void* unused, unsigned char *buf, size_t size) #endif int -BigIntegerCheckPrime(n, c) - BigInteger n; - BigIntegerCtx c; +BigIntegerCheckPrime(BigInteger n, BigIntegerCtx c) { #ifdef OPENSSL int rv; @@ -803,7 +760,11 @@ BigIntegerCheckPrime(n, c) if(c == NULL) c = ctx = BN_CTX_new(); #if OPENSSL_VERSION_NUMBER >= 0x00908000 - rv = BN_is_prime_ex(n, 25, c, NULL); + #if OPENSSL_VERSION_NUMBER >= 0x30000000L + rv = BN_check_prime(n, c, NULL); + #else + rv = BN_is_prime_ex(n, 25, c, NULL); + #endif #else rv = BN_is_prime(n, 25, NULL, c, NULL); #endif @@ -846,8 +807,7 @@ BigIntegerCheckPrime(n, c) } BigIntegerResult -BigIntegerFree(b) - BigInteger b; +BigIntegerFree(BigInteger b) { #ifdef OPENSSL BN_free(b); @@ -869,8 +829,7 @@ BigIntegerFree(b) } BigIntegerResult -BigIntegerClearFree(b) - BigInteger b; +BigIntegerClearFree(BigInteger b) { #ifdef OPENSSL BN_clear_free(b); @@ -906,8 +865,7 @@ BigIntegerCtxNew() } BigIntegerResult -BigIntegerCtxFree(ctx) - BigIntegerCtx ctx; +BigIntegerCtxFree(BigIntegerCtx ctx) { #ifdef OPENSSL if(ctx) @@ -917,9 +875,7 @@ BigIntegerCtxFree(ctx) } BigIntegerModAccel -BigIntegerModAccelNew(m, c) - BigInteger m; - BigIntegerCtx c; +BigIntegerModAccelNew(BigInteger m, BigIntegerCtx c) { #ifdef OPENSSL BN_CTX * ctx = NULL; @@ -939,8 +895,7 @@ BigIntegerModAccelNew(m, c) } BigIntegerResult -BigIntegerModAccelFree(accel) - BigIntegerModAccel accel; +BigIntegerModAccelFree(BigIntegerModAccel accel) { #ifdef OPENSSL if(accel) diff --git a/3rd_party/libsrp6a-sha512/t_misc.c b/3rd_party/libsrp6a-sha512/t_misc.c index 3053358..3a2cda1 100644 --- a/3rd_party/libsrp6a-sha512/t_misc.c +++ b/3rd_party/libsrp6a-sha512/t_misc.c @@ -80,8 +80,7 @@ SHA1_CTX randctxt; extern char ** environ; static void -t_envhash(out) - unsigned char * out; +t_envhash(unsigned char * out) { char ** ptr; char ebuf[256]; @@ -115,8 +114,7 @@ t_envhash(out) * The entire buffer is run once through SHA to obtain the final result. */ static void -t_fshash(out) - unsigned char * out; +t_fshash(unsigned char * out) { char dotpath[128]; struct stat st; @@ -317,9 +315,7 @@ t_stronginitrand() * Each cycle generates 20 bytes of new output. */ _TYPE( void ) -t_random(data, size) - unsigned char * data; - unsigned size; +t_random(unsigned char * data, unsigned size) { if(!initialized) t_initrand(); @@ -369,10 +365,7 @@ t_random(data, size) * single 320-bit value. */ _TYPE( unsigned char * ) -t_sessionkey(key, sk, sklen) - unsigned char * key; - unsigned char * sk; - unsigned sklen; +t_sessionkey(unsigned char * key, unsigned char * sk, unsigned sklen) { unsigned i, klen; unsigned char * hbuf; @@ -411,11 +404,7 @@ t_sessionkey(key, sk, sklen) } _TYPE( void ) -t_mgf1(mask, masklen, seed, seedlen) - unsigned char * mask; - unsigned masklen; - const unsigned char * seed; - unsigned seedlen; +t_mgf1(unsigned char * mask, unsigned masklen, const unsigned char * seed, unsigned seedlen) { SHA1_CTX ctxt; unsigned i = 0; diff --git a/3rd_party/libsrp6a-sha512/t_sha.c b/3rd_party/libsrp6a-sha512/t_sha.c index 4029de8..8e54cb6 100644 --- a/3rd_party/libsrp6a-sha512/t_sha.c +++ b/3rd_party/libsrp6a-sha512/t_sha.c @@ -107,6 +107,44 @@ SHA512Final_mbed(unsigned char digest[64], SHA512_CTX * ctx) mbedtls_md_free(ctx); } +#elif defined(OPENSSL_SHA) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +void +SHA1Init_openssl(SHA1_CTX *ctx) +{ + *ctx = EVP_MD_CTX_new(); + EVP_DigestInit(*ctx, EVP_sha1()); +} + +void SHA1Update_openssl(SHA1_CTX *ctx, const void *data, unsigned int len) +{ + EVP_DigestUpdate(*ctx, data, (size_t)len); +} + +void SHA1Final_openssl(unsigned char digest[20], SHA1_CTX *ctx) +{ + EVP_DigestFinal(*ctx, digest, NULL); + EVP_MD_CTX_destroy(*ctx); +} + +void +SHA512Init_openssl(SHA512_CTX *ctx) +{ + *ctx = EVP_MD_CTX_new(); + EVP_DigestInit(*ctx, EVP_sha512()); +} + +void SHA512Update_openssl(SHA512_CTX *ctx, const void *data, unsigned int len) +{ + EVP_DigestUpdate(*ctx, data, (size_t)len); +} + +void SHA512Final_openssl(unsigned char digest[64], SHA512_CTX *ctx) +{ + EVP_DigestFinal(*ctx, digest, NULL); + EVP_MD_CTX_destroy(*ctx); +} +#endif #elif !defined(OPENSSL_SHA) && !defined(TOMCRYPT_SHA) /* Use the free SHA1 if the library doesn't have it */ @@ -273,4 +311,4 @@ unsigned char finalcount[8]; SHA1Transform(context->state, context->buffer); #endif } -#endif /* OPENSSL */ +#endif diff --git a/3rd_party/libsrp6a-sha512/t_sha.h b/3rd_party/libsrp6a-sha512/t_sha.h index 18deec5..2e38067 100644 --- a/3rd_party/libsrp6a-sha512/t_sha.h +++ b/3rd_party/libsrp6a-sha512/t_sha.h @@ -38,6 +38,28 @@ #endif #ifdef OPENSSL_SHA +#include <openssl/err.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/evp.h> + +typedef EVP_MD_CTX* SHA1_CTX; +#define SHA1Init SHA1Init_openssl +#define SHA1Update SHA1Update_openssl +#define SHA1Final SHA1Final_openssl + +typedef EVP_MD_CTX* SHA512_CTX; +#define SHA512Init SHA512Init_openssl +#define SHA512Update SHA512Update_openssl +#define SHA512Final SHA512Final_openssl + +void SHA1Init_openssl(SHA1_CTX *ctx); +void SHA1Update_openssl(SHA1_CTX *ctx, const void *data, unsigned int len); +void SHA1Final_openssl(unsigned char digest[20], SHA1_CTX *ctx); + +void SHA512Init_openssl(SHA512_CTX *ctx); +void SHA512Update_openssl(SHA512_CTX *ctx, const void *data, unsigned int len); +void SHA512Final_openssl(unsigned char digest[64], SHA1_CTX *ctx); +#else /* for OpenSSL < 3.0 */ #include <openssl/sha.h> typedef SHA_CTX SHA1_CTX; @@ -48,7 +70,7 @@ typedef SHA_CTX SHA1_CTX; #define SHA512Init SHA512_Init #define SHA512Update SHA512_Update #define SHA512Final SHA512_Final - +#endif /* for OpenSSL < 3.0 */ #elif defined(TOMCRYPT_SHA) /* mycrypt.h already included above */ diff --git a/3rd_party/libsrp6a-sha512/t_truerand.c b/3rd_party/libsrp6a-sha512/t_truerand.c index 4a4c3d2..f995ed7 100644 --- a/3rd_party/libsrp6a-sha512/t_truerand.c +++ b/3rd_party/libsrp6a-sha512/t_truerand.c @@ -227,8 +227,7 @@ raw_truerand() } int -raw_n_truerand(n) -int n; +raw_n_truerand(int n) { int slop, v; diff --git a/common/Makefile.am b/common/Makefile.am index 1a90571..bd09bad 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -4,22 +4,16 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(GLOBAL_CFLAGS) \ + $(ssl_lib_CFLAGS) \ + $(LFS_CFLAGS) \ $(libusbmuxd_CFLAGS) \ - $(libplist_CFLAGS) \ - $(libgnutls_CFLAGS) \ - $(libtasn1_CFLAGS) \ - $(libgcrypt_CFLAGS) \ - $(openssl_CFLAGS) \ - $(LFS_CFLAGS) + $(libplist_CFLAGS) AM_LDFLAGS = \ + $(ssl_lib_LIBS) \ + ${libpthread_LIBS} \ $(libusbmuxd_LIBS) \ - $(libplist_LIBS) \ - $(libgnutls_LIBS) \ - $(libtasn1_LIBS) \ - $(libgcrypt_LIBS) \ - $(openssl_LIBS) \ - ${libpthread_LIBS} + $(libplist_LIBS) noinst_LTLIBRARIES = libinternalcommon.la libinternalcommon_la_LIBADD = diff --git a/common/debug.c b/common/debug.c index 6212e71..3492eaa 100644 --- a/common/debug.c +++ b/common/debug.c @@ -60,7 +60,7 @@ static void debug_print_line(const char *func, const char *file, int line, const strftime(str_time, 254, "%H:%M:%S", localtime (&the_time)); /* generate header text */ - (void)asprintf(&header, "%s %s:%d %s()", str_time, file, line, func); + if(asprintf(&header, "%s %s:%d %s()", str_time, file, line, func)<0){} free (str_time); /* trim ending newlines */ @@ -86,7 +86,7 @@ void debug_info_real(const char *func, const char *file, int line, const char *f /* run the real fprintf */ va_start(args, format); - (void)vasprintf(&buffer, format, args); + if(vasprintf(&buffer, format, args)<0){} va_end(args); debug_print_line(func, file, line, buffer); diff --git a/common/userpref.c b/common/userpref.c index ddd380a..b64c703 100644 --- a/common/userpref.c +++ b/common/userpref.c @@ -338,7 +338,7 @@ userpref_error_t userpref_read_pair_record(const char *udid, plist_t *pair_recor } *pair_record = NULL; - plist_from_memory(record_data, record_size, pair_record); + plist_from_memory(record_data, record_size, pair_record, NULL); free(record_data); if (!*pair_record) { @@ -435,6 +435,10 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da debug_info("Generating keys and certificates..."); #if defined(HAVE_OPENSSL) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY* root_pkey = EVP_RSA_gen(2048); + EVP_PKEY* host_pkey = EVP_RSA_gen(2048); +#else BIGNUM *e = BN_new(); RSA* root_keypair = RSA_new(); RSA* host_keypair = RSA_new(); @@ -451,6 +455,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da EVP_PKEY* host_pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(host_pkey, host_keypair); +#endif /* generate root certificate */ X509* root_cert = X509_new(); @@ -561,12 +566,22 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da } } - RSA *pubkey = NULL; + EVP_PKEY *pubkey = NULL; { BIO *membp = BIO_new_mem_buf(public_key.data, public_key.size); - if (!PEM_read_bio_RSAPublicKey(membp, &pubkey, NULL, NULL)) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (!PEM_read_bio_PUBKEY(membp, &pubkey, NULL, NULL)) { debug_info("WARNING: Could not read public key"); } +#else + RSA *rsa_pubkey = NULL; + if (!PEM_read_bio_RSAPublicKey(membp, &rsa_pubkey, NULL, NULL)) { + debug_info("WARNING: Could not read public key"); + } else { + pubkey = EVP_PKEY_new(); + EVP_PKEY_assign_RSA(pubkey, rsa_pubkey); + } +#endif BIO_free(membp); } @@ -588,10 +603,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da X509_set1_notAfter(dev_cert, asn1time); ASN1_TIME_free(asn1time); - EVP_PKEY* pkey = EVP_PKEY_new(); - EVP_PKEY_assign_RSA(pkey, pubkey); - X509_set_pubkey(dev_cert, pkey); - EVP_PKEY_free(pkey); + X509_set_pubkey(dev_cert, pubkey); X509_add_ext_helper(dev_cert, NID_subject_key_identifier, (char*)"hash"); X509_add_ext_helper(dev_cert, NID_key_usage, (char*)"critical,digitalSignature,keyEncipherment"); @@ -618,6 +630,7 @@ userpref_error_t pair_record_generate_keys_and_certs(plist_t pair_record, key_da X509V3_EXT_cleanup(); X509_free(dev_cert); + EVP_PKEY_free(pubkey); EVP_PKEY_free(root_pkey); EVP_PKEY_free(host_pkey); diff --git a/configure.ac b/configure.ac index 503051f..8ba094a 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ fi dnl Minimum package versions LIBUSBMUXD_VERSION=2.0.2 -LIBPLIST_VERSION=2.2.0 +LIBPLIST_VERSION=2.3.0 LIMD_GLUE_VERSION=1.0.0 AC_SUBST(LIBUSBMUXD_VERSION) diff --git a/cython/Makefile.am b/cython/Makefile.am index 3577c4e..93ea6ed 100644 --- a/cython/Makefile.am +++ b/cython/Makefile.am @@ -3,19 +3,15 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(GLOBAL_CFLAGS) \ - $(libgnutls_CFLAGS) \ - $(libtasn1_CFLAGS) \ - $(openssl_CFLAGS) \ - $(libplist_CFLAGS) \ + $(ssl_lib_CFLAGS) \ $(LFS_CFLAGS) \ - $(PTHREAD_CFLAGS) + $(PTHREAD_CFLAGS) \ + $(libplist_CFLAGS) AM_LIBS = \ - $(libgnutls_LIBS) \ - $(libtasn1_LIBS) \ - $(openssl_LIBS) \ - $(libplist_LIBS) \ - $(PTHREAD_LIBS) + $(ssl_lib_LIBS) \ + $(PTHREAD_LIBS) \ + $(libplist_LIBS) if HAVE_CYTHON diff --git a/docs/Makefile.am b/docs/Makefile.am index 9cdf82e..4a4c56f 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -16,6 +16,7 @@ man_MANS = \ idevicecrashreport.1 \ idevicename.1 \ idevicedebug.1 \ + idevicedevmodectl.1 \ idevicenotificationproxy.1 \ idevicesetlocation.1 diff --git a/docs/idevicedevmodectl.1 b/docs/idevicedevmodectl.1 new file mode 100644 index 0000000..5edaa80 --- /dev/null +++ b/docs/idevicedevmodectl.1 @@ -0,0 +1,58 @@ +.TH "idevicedevmodectl" 1 +.SH NAME +idevicedevmodectl \- Enable Developer Mode on iOS 16+ devices or print the current status. +.SH SYNOPSIS +.B idevicedevmodectl +COMMAND +[OPTIONS] + +.SH DESCRIPTION + +Enable Developer Mode on iOS 16+ devices or print the current status. + +.SH NOTE +Passcode-protected devices will NOT allow enabling of Developer Mode from the command line. It has to be enabled on the device itself under Settings -> Privacy & Security -> Developer Mode. +The \f[B]enable\f[] command will try to enable it, and tell you if that's the case. +If the menu is not shown, you may use the \f[B]reveal\f[] command to reveal it. + +.SH COMMANDS +.TP +.B list +Prints the Developer Mode status of all connected devices, or for a specific one if \f[B]\-\-udid\f[] is given. +.TP +.B enable +Enable Developer Mode (device will reboot), and confirm it after device booted up again. +.TP +.B arm +Arm the Developer Mode (device will reboot) +.TP +.B confirm +Confirm enabling of Developer Mode +.TP +.B reveal +Reveal the Developer Mode menu on the device under Settings -> Privacy & Security + +.SH OPTIONS +.TP +.B \-u, \-\-udid UDID +target specific device by UDID +.TP +.B \-n, \-\-network +connect to network device +.TP +.B \-d, \-\-debug +enable communication debugging +.TP +.B \-h, \-\-help +print usage information +.TP +.B \-v, \-\-version +print version information + +.SH AUTHORS +Nikias Bassen + +.SH ON THE WEB +https://libimobiledevice.org + +https://github.com/libimobiledevice/libimobiledevice diff --git a/git-version-gen b/git-version-gen index f6cb31c..d868952 100755 --- a/git-version-gen +++ b/git-version-gen @@ -16,4 +16,5 @@ else fi fi fi +VER=`printf %s "$VER" | head -n1` printf %s "$VER" diff --git a/src/Makefile.am b/src/Makefile.am index 1c80ed6..58cf07c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,19 +6,19 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(GLOBAL_CFLAGS) \ - $(libusbmuxd_CFLAGS) \ - $(libplist_CFLAGS) \ - $(limd_glue_CFLAGS) \ $(ssl_lib_CFLAGS) \ $(LFS_CFLAGS) \ - $(PTHREAD_CFLAGS) + $(PTHREAD_CFLAGS) \ + $(libusbmuxd_CFLAGS) \ + $(libplist_CFLAGS) \ + $(limd_glue_CFLAGS) AM_LDFLAGS = \ + $(ssl_lib_LIBS) \ + $(PTHREAD_LIBS) \ $(libusbmuxd_LIBS) \ $(libplist_LIBS) \ - $(limd_glue_LIBS) \ - $(ssl_lib_LIBS) \ - $(PTHREAD_LIBS) + $(limd_glue_LIBS) lib_LTLIBRARIES = libimobiledevice-1.0.la libimobiledevice_1_0_la_LIBADD = $(top_builddir)/common/libinternalcommon.la diff --git a/src/idevice.c b/src/idevice.c index 5930db9..719cd28 100644 --- a/src/idevice.c +++ b/src/idevice.c @@ -32,7 +32,11 @@ #ifdef WIN32 #include <winsock2.h> +#include <ws2tcpip.h> #include <windows.h> +#else +#include <sys/socket.h> +#include <netinet/in.h> #endif #include <usbmuxd.h> @@ -324,7 +328,21 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_get_device_list_extended(idevice_in newlist[newcount]->conn_data = NULL; } else if (dev_list[i].conn_type == CONNECTION_TYPE_NETWORK) { newlist[newcount]->conn_type = CONNECTION_NETWORK; - size_t addrlen = ((uint8_t*)dev_list[i].conn_data)[0]; + struct sockaddr* saddr = (struct sockaddr*)(dev_list[i].conn_data); + size_t addrlen = 0; + switch (saddr->sa_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; +#ifdef AF_INET6 + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; +#endif + default: + debug_info("Unsupported address family 0x%02x\n", saddr->sa_family); + continue; + } newlist[newcount]->conn_data = malloc(addrlen); memcpy(newlist[newcount]->conn_data, dev_list[i].conn_data, addrlen); } @@ -426,9 +444,25 @@ static idevice_t idevice_from_mux_device(usbmuxd_device_info_t *muxdev) break; case CONNECTION_TYPE_NETWORK: device->conn_type = CONNECTION_NETWORK; - size_t len = ((uint8_t*)muxdev->conn_data)[0]; - device->conn_data = malloc(len); - memcpy(device->conn_data, muxdev->conn_data, len); + struct sockaddr* saddr = (struct sockaddr*)(muxdev->conn_data); + size_t addrlen = 0; + switch (saddr->sa_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; +#ifdef AF_INET6 + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; +#endif + default: + debug_info("Unsupported address family 0x%02x\n", saddr->sa_family); + free(device->udid); + free(device); + return NULL; + } + device->conn_data = malloc(addrlen); + memcpy(device->conn_data, muxdev->conn_data, addrlen); break; default: device->conn_type = 0; @@ -515,27 +549,16 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connect(idevice_t device, uint16_t return IDEVICE_E_SUCCESS; } if (device->conn_type == CONNECTION_NETWORK) { - struct sockaddr_storage saddr_storage; - struct sockaddr* saddr = (struct sockaddr*)&saddr_storage; - - /* FIXME: Improve handling of this platform/host dependent connection data */ - if (((char*)device->conn_data)[1] == 0x02) { // AF_INET - saddr->sa_family = AF_INET; - memcpy(&saddr->sa_data[0], (char*)device->conn_data + 2, 14); - } - else if (((char*)device->conn_data)[1] == 0x1E) { // AF_INET6 (bsd) + struct sockaddr* saddr = (struct sockaddr*)(device->conn_data); + switch (saddr->sa_family) { + case AF_INET: #ifdef AF_INET6 - saddr->sa_family = AF_INET6; - /* copy the address and the host dependent scope id */ - memcpy(&saddr->sa_data[0], (char*)device->conn_data + 2, 26); -#else - debug_info("ERROR: Got an IPv6 address but this system doesn't support IPv6"); - return IDEVICE_E_UNKNOWN_ERROR; + case AF_INET6: #endif - } - else { - debug_info("Unsupported address family 0x%02x", ((char*)device->conn_data)[1]); - return IDEVICE_E_UNKNOWN_ERROR; + break; + default: + debug_info("Unsupported address family 0x%02x", saddr->sa_family); + return IDEVICE_E_UNKNOWN_ERROR; } char addrtxt[48]; @@ -1034,18 +1057,33 @@ static void internal_ssl_cleanup(ssl_data_t ssl_data) } #ifdef HAVE_OPENSSL +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, size_t len, int argi, long argl, int retvalue, size_t *processed) +#else static long ssl_idevice_bio_callback(BIO *b, int oper, const char *argp, int argi, long argl, long retvalue) +#endif { + ssize_t bytes = 0; idevice_connection_t conn = (idevice_connection_t)BIO_get_callback_arg(b); +#if OPENSSL_VERSION_NUMBER < 0x30000000L size_t len = (size_t)argi; + size_t *processed = (size_t*)&bytes; +#endif switch (oper) { case (BIO_CB_READ|BIO_CB_RETURN): - return argp ? (long)internal_ssl_read(conn, (char *)argp, len) : 0; + if (argp) { + bytes = internal_ssl_read(conn, (char *)argp, len); + *processed = bytes; + return (long)bytes; + } + return 0; case (BIO_CB_PUTS|BIO_CB_RETURN): len = strlen(argp); // fallthrough case (BIO_CB_WRITE|BIO_CB_RETURN): - return (long)internal_ssl_write(conn, argp, len); + bytes = internal_ssl_write(conn, argp, len); + *processed = bytes; + return (long)bytes; default: return retvalue; } @@ -1056,7 +1094,11 @@ static BIO *ssl_idevice_bio_new(idevice_connection_t conn) BIO *b = BIO_new(BIO_s_null()); if (!b) return NULL; BIO_set_callback_arg(b, (char *)conn); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + BIO_set_callback_ex(b, ssl_idevice_bio_callback); +#else BIO_set_callback(b, ssl_idevice_bio_callback); +#endif return b; } @@ -1190,15 +1232,13 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne /* force use of TLSv1 for older devices */ if (connection->device->version < DEVICE_VERSION(10,0,0)) { #ifdef SSL_OP_NO_TLSv1_1 - long opts = SSL_CTX_get_options(ssl_ctx); - opts |= SSL_OP_NO_TLSv1_1; + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_1); +#endif #ifdef SSL_OP_NO_TLSv1_2 - opts |= SSL_OP_NO_TLSv1_2; + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_2); #endif #ifdef SSL_OP_NO_TLSv1_3 - opts |= SSL_OP_NO_TLSv1_3; -#endif - SSL_CTX_set_options(ssl_ctx, opts); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); #endif } #else @@ -1207,7 +1247,8 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_VERSION); } #endif -#if (OPENSSL_VERSION_MAJOR >= 3) && defined(SSL_OP_IGNORE_UNEXPECTED_EOF) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if defined(SSL_OP_IGNORE_UNEXPECTED_EOF) /* * For OpenSSL 3 and later, mark close_notify alerts as optional. * For prior versions of OpenSSL we check for SSL_ERROR_SYSCALL when @@ -1215,6 +1256,14 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne */ SSL_CTX_set_options(ssl_ctx, SSL_OP_IGNORE_UNEXPECTED_EOF); #endif +#if defined(SSL_OP_LEGACY_SERVER_CONNECT) + /* + * Without setting SSL_OP_LEGACY_SERVER_CONNECT, OpenSSL 3 fails with + * error "unsafe legacy renegotiation disabled" when talking to iOS 5 + */ + SSL_CTX_set_options(ssl_ctx, SSL_OP_LEGACY_SERVER_CONNECT); +#endif +#endif BIO* membp; X509* rootCert = NULL; @@ -1227,6 +1276,16 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne X509_free(rootCert); free(root_cert.data); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_PKEY* rootPrivKey = NULL; + membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); + PEM_read_bio_PrivateKey(membp, &rootPrivKey, NULL, NULL); + BIO_free(membp); + if (SSL_CTX_use_PrivateKey(ssl_ctx, rootPrivKey) != 1) { + debug_info("WARNING: Could not load RootPrivateKey"); + } + EVP_PKEY_free(rootPrivKey); +#else RSA* rootPrivKey = NULL; membp = BIO_new_mem_buf(root_privkey.data, root_privkey.size); PEM_read_bio_RSAPrivateKey(membp, &rootPrivKey, NULL, NULL); @@ -1235,6 +1294,7 @@ LIBIMOBILEDEVICE_API idevice_error_t idevice_connection_enable_ssl(idevice_conne debug_info("WARNING: Could not load RootPrivateKey"); } RSA_free(rootPrivKey); +#endif free(root_privkey.data); SSL *ssl = SSL_new(ssl_ctx); diff --git a/src/installation_proxy.c b/src/installation_proxy.c index b13abf9..9602876 100644 --- a/src/installation_proxy.c +++ b/src/installation_proxy.c @@ -934,7 +934,7 @@ LIBIMOBILEDEVICE_API void instproxy_client_options_add(plist_t client_options, . if (!strcmp(key, "SkipUninstall")) { int intval = va_arg(args, int); plist_dict_set_item(client_options, key, plist_new_bool(intval)); - } else if (!strcmp(key, "ApplicationSINF") || !strcmp(key, "iTunesMetadata") || !strcmp(key, "ReturnAttributes")) { + } else if (!strcmp(key, "ApplicationSINF") || !strcmp(key, "iTunesMetadata") || !strcmp(key, "ReturnAttributes") || !strcmp(key, "BundleIDs")) { plist_t plistval = va_arg(args, plist_t); if (!plistval) { free(key); diff --git a/src/lockdown-cu.c b/src/lockdown-cu.c index 61a1c03..d8d7f42 100644 --- a/src/lockdown-cu.c +++ b/src/lockdown-cu.c @@ -1032,7 +1032,7 @@ LIBIMOBILEDEVICE_API lockdownd_error_t lockdownd_cu_send_request_and_get_reply(l plist_free(dict); dict = NULL; - plist_from_memory((const char*)decrypted, decrypted_len, &dict); + plist_from_memory((const char*)decrypted, decrypted_len, &dict, NULL); if (!dict) { ret = LOCKDOWN_E_PLIST_ERROR; debug_info("Failed to parse PLIST from decrypted payload:"); diff --git a/src/lockdown.c b/src/lockdown.c index 505b13e..92af186 100644 --- a/src/lockdown.c +++ b/src/lockdown.c @@ -165,51 +165,38 @@ lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_match) return ret; } - char *query_value = NULL; - - plist_get_string_val(query_node, &query_value); + const char *query_value = plist_get_string_ptr(query_node, NULL); if (!query_value) { return ret; } if (query_match && (strcmp(query_value, query_match) != 0)) { - free(query_value); return ret; } - free(query_value); - - plist_t result_node = plist_dict_get_item(dict, "Result"); - if (!result_node) { - /* iOS 5: the 'Result' key is not present anymore. - But we need to check for the 'Error' key. */ - plist_t err_node = plist_dict_get_item(dict, "Error"); - if (err_node) { - if (plist_get_node_type(err_node) == PLIST_STRING) { - char *err_value = NULL; - - plist_get_string_val(err_node, &err_value); - if (err_value) { - debug_info("ERROR: %s", err_value); - ret = lockdownd_strtoerr(err_value); - free(err_value); - } else { - debug_info("ERROR: unknown error occurred"); - } + /* Check for 'Error' in reply */ + plist_t err_node = plist_dict_get_item(dict, "Error"); + if (err_node) { + if (plist_get_node_type(err_node) == PLIST_STRING) { + const char *err_value = plist_get_string_ptr(err_node, NULL); + if (err_value) { + debug_info("ERROR: %s", err_value); + ret = lockdownd_strtoerr(err_value); + } else { + debug_info("ERROR: unknown error occurred"); } - return ret; } - - ret = LOCKDOWN_E_SUCCESS; - return ret; } - plist_type result_type = plist_get_node_type(result_node); - if (result_type == PLIST_STRING) { - char *result_value = NULL; - - plist_get_string_val(result_node, &result_value); + plist_t result_node = plist_dict_get_item(dict, "Result"); + if (!result_node) { + /* With iOS 5+ 'Result' is not present anymore. + If there is no 'Error', we can just assume success. */ + return LOCKDOWN_E_SUCCESS; + } + if (plist_get_node_type(result_node) == PLIST_STRING) { + const char *result_value = plist_get_string_ptr(result_node, NULL); if (result_value) { if (!strcmp(result_value, "Success")) { ret = LOCKDOWN_E_SUCCESS; @@ -219,9 +206,6 @@ lockdownd_error_t lockdown_check_result(plist_t dict, const char *query_match) debug_info("ERROR: unknown result value '%s'", result_value); } } - - if (result_value) - free(result_value); } return ret; diff --git a/src/mobilebackup.c b/src/mobilebackup.c index aa29277..1505623 100644 --- a/src/mobilebackup.c +++ b/src/mobilebackup.c @@ -279,7 +279,15 @@ LIBIMOBILEDEVICE_API mobilebackup_error_t mobilebackup_request_backup(mobileback char *str = NULL; plist_get_string_val(node, &str); if (str) { - if (strcmp(str, proto_version) != 0) { + int maj = 0; + int min = 0; + sscanf(str, "%u.%u", &maj, &min); + uint32_t this_ver = ((maj & 0xFF) << 8) | (min & 0xFF); + maj = 0; + min = 0; + sscanf(proto_version, "%u.%u", &maj, &min); + uint32_t proto_ver = ((maj & 0xFF) << 8) | (min & 0xFF); + if (this_ver > proto_ver) { err = MOBILEBACKUP_E_BAD_VERSION; } free(str); @@ -346,7 +354,15 @@ LIBIMOBILEDEVICE_API mobilebackup_error_t mobilebackup_request_restore(mobilebac char *str = NULL; plist_get_string_val(node, &str); if (str) { - if (strcmp(str, proto_version) != 0) { + int maj = 0; + int min = 0; + sscanf(str, "%u.%u", &maj, &min); + uint32_t this_ver = ((maj & 0xFF) << 8) | (min & 0xFF); + maj = 0; + min = 0; + sscanf(proto_version, "%u.%u", &maj, &min); + uint32_t proto_ver = ((maj & 0xFF) << 8) | (min & 0xFF); + if (this_ver > proto_ver) { err = MOBILEBACKUP_E_BAD_VERSION; } free(str); diff --git a/src/restore.c b/src/restore.c index 591fd16..41bfb9d 100644 --- a/src/restore.c +++ b/src/restore.c @@ -287,7 +287,7 @@ LIBIMOBILEDEVICE_API restored_error_t restored_get_value(restored_client_t clien } *value = plist_copy(item); - free(item); + return RESTORE_E_SUCCESS; } diff --git a/src/reverse_proxy.c b/src/reverse_proxy.c index 3f0a839..bca0a13 100644 --- a/src/reverse_proxy.c +++ b/src/reverse_proxy.c @@ -25,6 +25,9 @@ #endif #include <string.h> #include <stdlib.h> +#define _GNU_SOURCE 1 +#define __USE_GNU 1 +#include <stdio.h> #include <errno.h> #include <plist/plist.h> @@ -91,7 +94,7 @@ static void _reverse_proxy_log(reverse_proxy_client_t client, const char* format va_list args; va_start(args, format); char* buffer = NULL; - (void)vasprintf(&buffer, format, args); + if(vasprintf(&buffer, format, args)<0){} va_end(args); client->log_cb(client, buffer, client->log_cb_user_data); free(buffer); @@ -113,7 +116,7 @@ static void _reverse_proxy_status(reverse_proxy_client_t client, int status, con va_list args; va_start(args, format); char* buffer = NULL; - (void)vasprintf(&buffer, format, args); + if(vasprintf(&buffer, format, args)<0){} va_end(args); client->status_cb(client, status, buffer, client->status_cb_user_data); free(buffer); @@ -186,10 +189,10 @@ static int _reverse_proxy_handle_proxy_cmd(reverse_proxy_client_t client) /* else wait for messages and forward them */ int sockfd = socket_connect(host, port); - free(host); if (sockfd < 0) { free(buf); _reverse_proxy_log(client, "ERROR: Connection to %s:%u failed: %s", host, port, strerror(errno)); + free(host); return -1; } @@ -259,6 +262,7 @@ static int _reverse_proxy_handle_proxy_cmd(reverse_proxy_client_t client) } } socket_close(sockfd); + free(host); free(buf); _reverse_proxy_status(client, RP_STATUS_DISCONNECTED, "Disconnected (out: %u / in: %u)", sent_total, recv_total); diff --git a/tools/Makefile.am b/tools/Makefile.am index e8ef3ab..bd93631 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -4,6 +4,7 @@ AM_CPPFLAGS = \ AM_CFLAGS = \ $(GLOBAL_CFLAGS) \ + $(ssl_lib_CFLAGS) \ $(libplist_CFLAGS) \ $(LFS_CFLAGS) @@ -27,6 +28,7 @@ bin_PROGRAMS = \ idevicedebugserverproxy \ idevicediagnostics \ idevicedebug \ + idevicedevmodectl \ idevicenotificationproxy \ idevicecrashreport \ idevicesetlocation @@ -47,7 +49,7 @@ idevicename_LDFLAGS = $(AM_LDFLAGS) idevicename_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la idevicepair_SOURCES = idevicepair.c -idevicepair_CFLAGS = $(AM_CFLAGS) $(ssl_lib_CFLAGS) +idevicepair_CFLAGS = $(AM_CFLAGS) idevicepair_LDFLAGS = $(AM_LDFLAGS) $(libusbmuxd_LIBS) $(ssl_lib_LIBS) idevicepair_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la $(limd_glue_LIBS) @@ -62,7 +64,7 @@ idevice_id_LDFLAGS = $(AM_LDFLAGS) idevice_id_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la idevicebackup_SOURCES = idevicebackup.c -idevicebackup_CFLAGS = $(AM_CFLAGS) $(ssl_lib_CFLAGS) $(limd_glue_CFLAGS) +idevicebackup_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) idevicebackup_LDFLAGS = $(AM_LDFLAGS) $(ssl_lib_LIBS) $(limd_glue_LIBS) idevicebackup_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la @@ -111,6 +113,11 @@ idevicedebug_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) idevicedebug_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) idevicedebug_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la +idevicedevmodectl_SOURCES = idevicedevmodectl.c +idevicedevmodectl_CFLAGS = $(AM_CFLAGS) $(limd_glue_CFLAGS) +idevicedevmodectl_LDFLAGS = $(AM_LDFLAGS) $(limd_glue_LIBS) +idevicedevmodectl_LDADD = $(top_builddir)/src/libimobiledevice-1.0.la $(top_builddir)/common/libinternalcommon.la + idevicenotificationproxy_SOURCES = idevicenotificationproxy.c idevicenotificationproxy_CFLAGS = $(AM_CFLAGS) idevicenotificationproxy_LDFLAGS = $(AM_LDFLAGS) diff --git a/tools/idevicebackup.c b/tools/idevicebackup.c index 2856fda..5694c12 100644 --- a/tools/idevicebackup.c +++ b/tools/idevicebackup.c @@ -34,6 +34,9 @@ #include <getopt.h> #if defined(HAVE_OPENSSL) #include <openssl/sha.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include <openssl/evp.h> +#endif #elif defined(HAVE_GNUTLS) #include <gcrypt.h> #elif defined(HAVE_MBEDTLS) @@ -57,6 +60,7 @@ #include <libimobiledevice/notification_proxy.h> #include <libimobiledevice/afc.h> #include <libimobiledevice-glue/utils.h> +#include <plist/plist.h> #define MOBILEBACKUP_SERVICE_NAME "com.apple.mobilebackup" #define NP_SERVICE_NAME "com.apple.mobile.notification_proxy" @@ -112,7 +116,11 @@ static int compare_hash(const unsigned char *hash1, const unsigned char *hash2, static void _sha1_update(void* context, const char* data, size_t len) { #if defined(HAVE_OPENSSL) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_DigestUpdate(context, data, len); +#else SHA1_Update(context, data, len); +#endif #elif defined(HAVE_GNUTLS) gcry_md_write(context, data, len); #elif defined(HAVE_MBEDTLS) @@ -123,9 +131,15 @@ static void _sha1_update(void* context, const char* data, size_t len) static void compute_datahash(const char *path, const char *destpath, uint8_t greylist, const char *domain, const char *appid, const char *version, unsigned char *hash_out) { #if defined(HAVE_OPENSSL) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD_CTX* sha1 = EVP_MD_CTX_new(); + EVP_DigestInit(sha1, EVP_sha1()); + void* psha1 = sha1; +#else SHA_CTX sha1; SHA1_Init(&sha1); void* psha1 = &sha1; +#endif #elif defined(HAVE_GNUTLS) gcry_md_hd_t hd = NULL; gcry_md_open(&hd, GCRY_MD_SHA1, 0); @@ -179,7 +193,12 @@ static void compute_datahash(const char *path, const char *destpath, uint8_t gre _sha1_update(psha1, "(null)", 6); } #if defined(HAVE_OPENSSL) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_DigestFinal(sha1, hash_out, NULL); + EVP_MD_CTX_destroy(sha1); +#else SHA1_Final(hash_out, &sha1); +#endif #elif defined(HAVE_GNUTLS) unsigned char *newhash = gcry_md_read(hd, GCRY_MD_SHA1); memcpy(hash_out, newhash, 20); @@ -317,7 +336,7 @@ static void mobilebackup_write_status(const char *path, int status) if (stat(file_path, &st) == 0) remove(file_path); - plist_write_to_filename(status_plist, file_path, PLIST_FORMAT_XML); + plist_write_to_file(status_plist, file_path, PLIST_FORMAT_XML, 0); plist_free(status_plist); status_plist = NULL; @@ -331,7 +350,7 @@ static int mobilebackup_read_status(const char *path) plist_t status_plist = NULL; char *file_path = mobilebackup_build_path(path, "Status", ".plist"); - plist_read_from_filename(&status_plist, file_path); + plist_read_from_file(file_path, &status_plist, NULL); free(file_path); if (!status_plist) { printf("Could not read Status.plist!\n"); @@ -454,7 +473,7 @@ static int mobilebackup_check_file_integrity(const char *backup_directory, const } infopath = mobilebackup_build_path(backup_directory, hash, ".mdinfo"); - plist_read_from_filename(&mdinfo, infopath); + plist_read_from_file(infopath, &mdinfo, NULL); free(infopath); if (!mdinfo) { printf("\r\n"); @@ -882,7 +901,7 @@ int main(int argc, char *argv[]) /* verify existing Info.plist */ if (stat(info_path, &st) == 0) { printf("Reading Info.plist from backup.\n"); - plist_read_from_filename(&info_plist, info_path); + plist_read_from_file(info_path, &info_plist, NULL); if (!info_plist) { printf("Could not read Info.plist\n"); @@ -893,7 +912,7 @@ int main(int argc, char *argv[]) /* update the last backup time within Info.plist */ mobilebackup_info_update_last_backup_date(info_plist); remove(info_path); - plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + plist_write_to_file(info_plist, info_path, PLIST_FORMAT_XML, 0); } else { printf("Aborting backup. Backup is not compatible with the current device.\n"); cmd = CMD_LEAVE; @@ -959,7 +978,7 @@ int main(int argc, char *argv[]) /* read the last Manifest.plist */ if (!is_full_backup) { printf("Reading existing Manifest.\n"); - plist_read_from_filename(&manifest_plist, manifest_path); + plist_read_from_file(manifest_path, &manifest_plist, NULL); if (!manifest_plist) { printf("Could not read Manifest.plist, switching to full backup mode.\n"); is_full_backup = 1; @@ -977,7 +996,7 @@ int main(int argc, char *argv[]) remove(info_path); printf("Creating Info.plist for new backup.\n"); info_plist = mobilebackup_factory_info_plist_new(udid); - plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + plist_write_to_file(info_plist, info_path, PLIST_FORMAT_XML, 0); } free(info_path); @@ -1116,7 +1135,7 @@ int main(int argc, char *argv[]) remove(filename_mdinfo); node = plist_dict_get_item(node_tmp, "BackupFileInfo"); - plist_write_to_filename(node, filename_mdinfo, PLIST_FORMAT_BINARY); + plist_write_to_file(node, filename_mdinfo, PLIST_FORMAT_BINARY, 0); free(filename_mdinfo); } @@ -1228,7 +1247,7 @@ files_out: if (manifest_plist) { remove(manifest_path); printf("Storing Manifest.plist...\n"); - plist_write_to_filename(manifest_plist, manifest_path, PLIST_FORMAT_XML); + plist_write_to_file(manifest_plist, manifest_path, PLIST_FORMAT_XML, 0); } backup_ok = 1; @@ -1259,7 +1278,7 @@ files_out: } /* now make sure backup integrity is ok! verify all files */ printf("Reading existing Manifest.\n"); - plist_read_from_filename(&manifest_plist, manifest_path); + plist_read_from_file(manifest_path, &manifest_plist, NULL); if (!manifest_plist) { printf("Could not read Manifest.plist. Aborting.\n"); break; @@ -1386,7 +1405,7 @@ files_out: while (node) { /* TODO: read mddata/mdinfo files and send to device using DLSendFile */ file_info_path = mobilebackup_build_path(backup_directory, hash, ".mdinfo"); - plist_read_from_filename(&file_info, file_info_path); + plist_read_from_file(file_info_path, &file_info, NULL); /* get encryption state */ tmp_node = plist_dict_get_item(file_info, "IsEncrypted"); diff --git a/tools/idevicebackup2.c b/tools/idevicebackup2.c index f2242d2..c73b269 100644 --- a/tools/idevicebackup2.c +++ b/tools/idevicebackup2.c @@ -47,6 +47,7 @@ #include <libimobiledevice/sbservices.h> #include <libimobiledevice/diagnostics_relay.h> #include <libimobiledevice-glue/utils.h> +#include <plist/plist.h> #include <endianness.h> @@ -606,7 +607,7 @@ static int mb2_status_check_snapshot_state(const char *path, const char *udid, c plist_t status_plist = NULL; char *file_path = string_build_path(path, udid, "Status.plist", NULL); - plist_read_from_filename(&status_plist, file_path); + plist_read_from_file(file_path, &status_plist, NULL); free(file_path); if (!status_plist) { printf("Could not read Status.plist!\n"); @@ -1555,6 +1556,7 @@ int main(int argc, char *argv[]) return 2; } source_udid = strdup(optarg); + break; case 'i': interactive_mode = 1; break; @@ -1779,7 +1781,7 @@ int main(int argc, char *argv[]) free(info_path); } plist_t manifest_plist = NULL; - plist_read_from_filename(&manifest_plist, manifest_path); + plist_read_from_file(manifest_path, &manifest_plist, NULL); if (!manifest_plist) { idevice_free(device); free(info_path); @@ -1935,7 +1937,7 @@ int main(int argc, char *argv[]) /* verify existing Info.plist */ if (info_path && (stat(info_path, &st) == 0) && cmd != CMD_CLOUD) { PRINT_VERBOSE(1, "Reading Info.plist from backup.\n"); - plist_read_from_filename(&info_plist, info_path); + plist_read_from_file(info_path, &info_plist, NULL); if (!info_plist) { printf("Could not read Info.plist\n"); @@ -2029,7 +2031,7 @@ checkpoint: cmd = CMD_LEAVE; } remove_file(info_path); - plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML); + plist_write_to_file(info_plist, info_path, PLIST_FORMAT_XML, 0); free(info_path); plist_free(info_plist); diff --git a/tools/idevicecrashreport.c b/tools/idevicecrashreport.c index d0d2147..09bd537 100644 --- a/tools/idevicecrashreport.c +++ b/tools/idevicecrashreport.c @@ -81,7 +81,7 @@ static int extract_raw_crash_report(const char* filename) strcpy(p, ".crash"); /* read plist crash report */ - if (plist_read_from_filename(&report, filename)) { + if (plist_read_from_file(filename, &report, NULL)) { plist_t description_node = plist_dict_get_item(report, "description"); if (description_node && plist_get_node_type(description_node) == PLIST_STRING) { plist_get_string_val(description_node, &raw); @@ -163,7 +163,7 @@ static int afc_client_copy_and_remove_crash_reports(afc_client_t afc, const char char* p = strrchr(list[k], '.'); if (p != NULL && !strncmp(p, ".synced", 7)) { /* make sure to strip ".synced" extension as seen on iOS 5 */ - int newlen = strlen(list[k]) - 7; + size_t newlen = p - list[k]; strncpy(((char*)target_filename) + host_directory_length, list[k], newlen); target_filename[host_directory_length + newlen] = '\0'; } else { diff --git a/tools/idevicedebug.c b/tools/idevicedebug.c index fbb6c3e..36c594e 100644 --- a/tools/idevicedebug.c +++ b/tools/idevicedebug.c @@ -291,6 +291,11 @@ int main(int argc, char *argv[]) res = 0; goto cleanup; break; + default: + print_usage(argc, argv, 1); + res = 2; + goto cleanup; + break; } } argc -= optind; diff --git a/tools/idevicedevmodectl.c b/tools/idevicedevmodectl.c new file mode 100644 index 0000000..ba9b935 --- /dev/null +++ b/tools/idevicedevmodectl.c @@ -0,0 +1,452 @@ +/* + * idevicedevmodectl.c + * List or enable Developer Mode on iOS 16+ devices + * + * Copyright (c) 2022 Nikias Bassen, All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#define TOOL_NAME "idevicedevmodectl" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#ifndef WIN32 +#include <signal.h> +#endif + +#ifdef WIN32 +#include <windows.h> +#define __usleep(x) Sleep(x/1000) +#else +#include <arpa/inet.h> +#define __usleep(x) usleep(x) +#endif + +#include <libimobiledevice/libimobiledevice.h> +#include <libimobiledevice/lockdown.h> +#include <libimobiledevice/property_list_service.h> +#include <libimobiledevice-glue/utils.h> + +#define AMFI_LOCKDOWN_SERVICE_NAME "com.apple.amfi.lockdown" + +static char* udid = NULL; +static int use_network = 0; + +static void print_usage(int argc, char **argv, int is_error) +{ + char *name = strrchr(argv[0], '/'); + fprintf(is_error ? stderr : stdout, "Usage: %s [OPTIONS] COMMAND\n", (name ? name + 1: argv[0])); + fprintf(is_error ? stderr : stdout, + "\n" + "Enable Developer Mode on iOS 16+ devices or print the current status.\n" + "\n" + "Where COMMAND is one of:\n" + " list Print the Developer Mode status of all connected devices\n" + " or for a specific one if --udid is given.\n" + " enable Enable Developer Mode (device will reboot),\n" + " and confirm it after device booted up again.\n" + "\n" + " arm Arm the Developer Mode (device will reboot)\n" + " confirm Confirm enabling of Developer Mode\n" + " reveal Reveal the Developer Mode menu on the device\n" + "\n" + "The following OPTIONS are accepted:\n" + " -u, --udid UDID target specific device by UDID\n" + " -n, --network connect to network device\n" + " -d, --debug enable communication debugging\n" + " -h, --help print usage information\n" + " -v, --version print version information\n" + "\n" + "Homepage: <" PACKAGE_URL ">\n" + "Bug Reports: <" PACKAGE_BUGREPORT ">\n" + ); +} + +enum { + OP_LIST, + OP_ENABLE, + OP_ARM, + OP_CONFIRM, + OP_REVEAL, + NUM_OPS +}; +#define DEV_MODE_REVEAL 0 +#define DEV_MODE_ARM 1 +#define DEV_MODE_ENABLE 2 + +static int get_developer_mode_status(const char* device_udid, int _use_network) +{ + idevice_error_t ret; + idevice_t device = NULL; + lockdownd_client_t lockdown = NULL; + lockdownd_error_t lerr = LOCKDOWN_E_UNKNOWN_ERROR; + plist_t val = NULL; + + ret = idevice_new_with_options(&device, device_udid, (_use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); + if (ret != IDEVICE_E_SUCCESS) { + return -1; + } + + if (LOCKDOWN_E_SUCCESS != (lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME))) { + idevice_free(device); + return -1; + } + + lerr = lockdownd_get_value(lockdown, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); + if (lerr != LOCKDOWN_E_SUCCESS) { + fprintf(stderr, "ERROR: Could not get DeveloperModeStatus: %s\nPlease note that this feature is only available on iOS 16+.\n", lockdownd_strerror(lerr)); + lockdownd_client_free(lockdown); + idevice_free(device); + return -2; + } + + uint8_t dev_mode_status = 0; + plist_get_bool_val(val, &dev_mode_status); + plist_free(val); + + lockdownd_client_free(lockdown); + idevice_free(device); + + return dev_mode_status; +} + +static int amfi_service_send_msg(property_list_service_client_t amfi, plist_t msg) +{ + int res; + property_list_service_error_t perr; + + perr = property_list_service_send_xml_plist(amfi, plist_copy(msg)); + if (perr != PROPERTY_LIST_SERVICE_E_SUCCESS) { + fprintf(stderr, "Could not send request to device: %d\n", perr); + res = 2; + } else { + plist_t reply = NULL; + perr = property_list_service_receive_plist(amfi, &reply); + if (perr == PROPERTY_LIST_SERVICE_E_SUCCESS) { + uint8_t success = 0; + plist_t val = plist_dict_get_item(reply, "Error"); + if (val) { + const char* err = plist_get_string_ptr(val, NULL); + fprintf(stderr, "Request failed: %s\n", err); + if (strstr(err, "passcode")) { + res = 2; + } else { + res = 1; + } + } else { + val = plist_dict_get_item(reply, "success"); + if (val) { + plist_get_bool_val(val, &success); + } + if (success) { + res = 0; + } else { + res = 1; + } + } + } else { + fprintf(stderr, "Could not receive reply from device: %d\n", perr); + res = 2; + } + plist_free(reply); + } + return res; +} + +static int amfi_send_action(idevice_t device, unsigned int action) +{ + lockdownd_client_t lockdown = NULL; + lockdownd_service_descriptor_t service = NULL; + lockdownd_error_t lerr; + + if (LOCKDOWN_E_SUCCESS != (lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME))) { + fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", lerr); + return 1; + } + + lerr = lockdownd_start_service(lockdown, AMFI_LOCKDOWN_SERVICE_NAME, &service); + if (lerr != LOCKDOWN_E_SUCCESS) { + fprintf(stderr, "Could not start service %s: %s\nPlease note that this feature is only available on iOS 16+.\n", AMFI_LOCKDOWN_SERVICE_NAME, lockdownd_strerror(lerr)); + lockdownd_client_free(lockdown); + return 1; + } + lockdownd_client_free(lockdown); + lockdown = NULL; + + property_list_service_client_t amfi = NULL; + if (property_list_service_client_new(device, service, &amfi) != PROPERTY_LIST_SERVICE_E_SUCCESS) { + fprintf(stderr, "Could not connect to %s on device\n", AMFI_LOCKDOWN_SERVICE_NAME); + if (service) + lockdownd_service_descriptor_free(service); + idevice_free(device); + return 1; + } + lockdownd_service_descriptor_free(service); + + plist_t dict = plist_new_dict(); + plist_dict_set_item(dict, "action", plist_new_uint(action)); + + int result = amfi_service_send_msg(amfi, dict); + plist_free(dict); + + property_list_service_client_free(amfi); + amfi = NULL; + + return result; +} + +static int device_connected = 0; + +static void device_event_cb(const idevice_event_t* event, void* userdata) +{ + if (use_network && event->conn_type != CONNECTION_NETWORK) { + return; + } + if (!use_network && event->conn_type != CONNECTION_USBMUXD) { + return; + } + if (event->event == IDEVICE_DEVICE_ADD) { + if (!udid) { + udid = strdup(event->udid); + } + if (strcmp(udid, event->udid) == 0) { + device_connected = 1; + } + } else if (event->event == IDEVICE_DEVICE_REMOVE) { + if (strcmp(udid, event->udid) == 0) { + device_connected = 0; + } + } +} + + +#define WAIT_INTERVAL 200000 +#define WAIT_MAX(x) (x * (1000000 / WAIT_INTERVAL)) +#define WAIT_FOR(cond, timeout) { int __repeat = WAIT_MAX(timeout); while (!(cond) && __repeat-- > 0) { __usleep(WAIT_INTERVAL); } } + +int main(int argc, char *argv[]) +{ + idevice_t device = NULL; + idevice_error_t ret = IDEVICE_E_UNKNOWN_ERROR; + lockdownd_client_t lockdown = NULL; + lockdownd_error_t lerr = LOCKDOWN_E_UNKNOWN_ERROR; + int res = 0; + int i; + int op = -1; + plist_t val = NULL; + + int c = 0; + const struct option longopts[] = { + { "debug", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "udid", required_argument, NULL, 'u' }, + { "network", no_argument, NULL, 'n' }, + { "version", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0} + }; + +#ifndef WIN32 + signal(SIGPIPE, SIG_IGN); +#endif + /* parse cmdline args */ + while ((c = getopt_long(argc, argv, "dhu:nv", longopts, NULL)) != -1) { + switch (c) { + case 'd': + idevice_set_debug_level(1); + break; + case 'u': + if (!*optarg) { + fprintf(stderr, "ERROR: UDID argument must not be empty!\n"); + print_usage(argc, argv, 1); + return 2; + } + udid = optarg; + break; + case 'n': + use_network = 1; + break; + case 'h': + print_usage(argc, argv, 0); + return 0; + case 'v': + printf("%s %s\n", TOOL_NAME, PACKAGE_VERSION); + return 0; + default: + print_usage(argc, argv, 1); + return 2; + } + } + argc -= optind; + argv += optind; + + if (!argv[0]) { + fprintf(stderr, "ERROR: Missing command.\n"); + print_usage(argc+optind, argv-optind, 1); + return 2; + } + + i = 0; + if (!strcmp(argv[i], "list")) { + op = OP_LIST; + } + else if (!strcmp(argv[i], "enable")) { + op = OP_ENABLE; + } + else if (!strcmp(argv[i], "arm")) { + op = OP_ARM; + } + else if (!strcmp(argv[i], "confirm")) { + op = OP_CONFIRM; + } + else if (!strcmp(argv[i], "reveal")) { + op = OP_REVEAL; + } + + if ((op == -1) || (op >= NUM_OPS)) { + fprintf(stderr, "ERROR: Unsupported command '%s'\n", argv[i]); + print_usage(argc+optind, argv-optind, 1); + return 2; + } + + if (op == OP_LIST) { + idevice_info_t *dev_list = NULL; + + if (idevice_get_device_list_extended(&dev_list, &i) < 0) { + fprintf(stderr, "ERROR: Unable to retrieve device list!\n"); + return -1; + } + if (i > 0) { + printf("%-40s %s\n", "Device", "DeveloperMode"); + } + for (i = 0; dev_list[i] != NULL; i++) { + if (dev_list[i]->conn_type == CONNECTION_USBMUXD && use_network) continue; + if (dev_list[i]->conn_type == CONNECTION_NETWORK && !use_network) continue; + if (udid && (strcmp(dev_list[i]->udid, udid) != 0)) continue; + int mode = get_developer_mode_status(dev_list[i]->udid, use_network); + const char *mode_str = "N/A"; + if (mode == 1) { + mode_str = "enabled"; + } else if (mode == 0) { + mode_str = "disabled"; + } + printf("%-40s %s\n", dev_list[i]->udid, mode_str); + } + idevice_device_list_extended_free(dev_list); + + return 0; + } + + idevice_subscription_context_t context = NULL; + idevice_events_subscribe(&context, device_event_cb, NULL); + + WAIT_FOR(device_connected, 10); + + ret = idevice_new_with_options(&device, udid, (use_network) ? IDEVICE_LOOKUP_NETWORK : IDEVICE_LOOKUP_USBMUX); + if (ret != IDEVICE_E_SUCCESS) { + if (udid) { + printf("No device found with udid %s.\n", udid); + } else { + printf("No device found.\n"); + } + return 1; + } + + if (!udid) { + idevice_get_udid(device, &udid); + } + + if (LOCKDOWN_E_SUCCESS != (lerr = lockdownd_client_new_with_handshake(device, &lockdown, TOOL_NAME))) { + fprintf(stderr, "ERROR: Could not connect to lockdownd, error code %d\n", lerr); + idevice_free(device); + return 1; + } + + lerr = lockdownd_get_value(lockdown, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); + lockdownd_client_free(lockdown); + lockdown = NULL; + if (lerr != LOCKDOWN_E_SUCCESS) { + fprintf(stderr, "ERROR: Could not get DeveloperModeStatus: %s\nPlease note that this feature is only available on iOS 16+.\n", lockdownd_strerror(lerr)); + idevice_free(device); + return 1; + } + + uint8_t dev_mode_status = 0; + plist_get_bool_val(val, &dev_mode_status); + + if ((op == OP_ENABLE || op == OP_ARM) && dev_mode_status) { + if (dev_mode_status) { + printf("DeveloperMode is already enabled.\n"); + return 0; + } + res = 0; + } else { + if (op == OP_ENABLE || op == OP_ARM) { + res = amfi_send_action(device, DEV_MODE_ARM); + if (res == 0) { + if (op == OP_ARM) { + printf("%s: Developer Mode armed, device will reboot now.\n", udid); + } else { + printf("%s: Developer Mode armed, waiting for reboot...\n", udid); + + // waiting for device to disconnect... + WAIT_FOR(!device_connected, 20); + + // waiting for device to reconnect... + WAIT_FOR(device_connected, 60); + + res = amfi_send_action(device, DEV_MODE_ENABLE); + if (res == 0) { + printf("%s: Developer Mode successfully enabled.\n", udid); + } else { + printf("%s: Failed to enable developer mode (%d)\n", udid, res); + } + } + } else if (res == 2) { + amfi_send_action(device, DEV_MODE_REVEAL); + printf("%s: Developer Mode could not be enabled because the device has a passcode set. You have to enable it on the device itself under Settings -> Privacy & Security -> Developer Mode.\n", udid); + } else { + printf("%s: Failed to arm Developer Mode (%d)\n", udid, res); + } + } else if (op == OP_CONFIRM) { + res = amfi_send_action(device, DEV_MODE_ENABLE); + if (res == 0) { + printf("%s: Developer Mode successfully enabled.\n", udid); + } else { + printf("%s: Failed to enable Developer Mode (%d)\n", udid, res); + } + } else if (op == OP_REVEAL) { + res = amfi_send_action(device, DEV_MODE_REVEAL); + if (res == 0) { + printf("%s: Developer Mode menu revealed successfully.\n", udid); + } else { + printf("%s: Failed to reveal Developer Mode menu (%d)\n", udid, res); + } + } + } + + idevice_free(device); + + return res; +} diff --git a/tools/ideviceimagemounter.c b/tools/ideviceimagemounter.c index b854d5d..f551b6c 100644 --- a/tools/ideviceimagemounter.c +++ b/tools/ideviceimagemounter.c @@ -46,7 +46,7 @@ #include <libimobiledevice/notification_proxy.h> #include <libimobiledevice/mobile_image_mounter.h> #include <asprintf.h> -#include <libimobiledevice-glue/utils.h> +#include <plist/plist.h> static int list_mode = 0; static int use_network = 0; @@ -143,15 +143,6 @@ static void parse_opts(int argc, char **argv) } } -static void print_xml(plist_t node) -{ - char *xml = NULL; - uint32_t len = 0; - plist_to_xml(node, &xml, &len); - if (xml) - puts(xml); -} - static ssize_t mim_upload_cb(void* buf, size_t size, void* userdata) { return fread(buf, 1, size, (FILE*)userdata); @@ -224,6 +215,20 @@ int main(int argc, char **argv) } } + if (product_version_major == 16) { + uint8_t dev_mode_status = 0; + plist_t val = NULL; + ldret = lockdownd_get_value(lckd, "com.apple.security.mac.amfi", "DeveloperModeStatus", &val); + if (ldret == LOCKDOWN_E_SUCCESS) { + plist_get_bool_val(val, &dev_mode_status); + plist_free(val); + } + if (!dev_mode_status) { + printf("ERROR: You have to enable Developer Mode on the given device in order to allowing mounting a developer disk image.\n"); + goto leave; + } + } + lockdownd_start_service(lckd, "com.apple.mobile.mobile_image_mounter", &service); if (!service || service->port == 0) { @@ -283,11 +288,7 @@ int main(int argc, char **argv) err = mobile_image_mounter_lookup_image(mim, imagetype, &result); if (err == MOBILE_IMAGE_MOUNTER_E_SUCCESS) { res = 0; - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } else { printf("Error: lookup_image returned %d\n", err); } @@ -415,20 +416,12 @@ int main(int argc, char **argv) res = 0; } else { printf("unexpected status value:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } free(status); } else { printf("unexpected result:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } node = plist_dict_get_item(result, "Error"); @@ -440,19 +433,11 @@ int main(int argc, char **argv) free(error); } else { printf("unexpected result:\n"); - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } else { - if (xml_mode) { - print_xml(result); - } else { - plist_print_to_stream(result, stdout); - } + plist_write_to_stream(result, stdout, (xml_mode) ? PLIST_FORMAT_XML : PLIST_FORMAT_LIMD, 0); } } } else { diff --git a/tools/ideviceinfo.c b/tools/ideviceinfo.c index fc0527d..fd45763 100644 --- a/tools/ideviceinfo.c +++ b/tools/ideviceinfo.c @@ -37,7 +37,7 @@ #include <libimobiledevice/libimobiledevice.h> #include <libimobiledevice/lockdown.h> -#include <libimobiledevice-glue/utils.h> +#include <plist/plist.h> #define FORMAT_KEY_VALUE 1 #define FORMAT_XML 2 @@ -241,11 +241,11 @@ int main(int argc, char *argv[]) free(xml_doc); break; case FORMAT_KEY_VALUE: - plist_print_to_stream(node, stdout); + plist_write_to_stream(node, stdout, PLIST_FORMAT_LIMD, 0); break; default: if (key != NULL) - plist_print_to_stream(node, stdout); + plist_write_to_stream(node, stdout, PLIST_FORMAT_LIMD, 0); break; } plist_free(node); diff --git a/tools/idevicepair.c b/tools/idevicepair.c index dda02ec..94d3f04 100644 --- a/tools/idevicepair.c +++ b/tools/idevicepair.c @@ -41,7 +41,6 @@ #endif #include "common/userpref.h" -#include <libimobiledevice-glue/utils.h> #include <libimobiledevice/libimobiledevice.h> #include <libimobiledevice/lockdown.h> @@ -104,7 +103,7 @@ static void pairing_cb(lockdownd_cu_pairing_cb_type_t cb_type, void *user_data, printf("\n"); } else if (cb_type == LOCKDOWN_CU_PAIRING_DEVICE_INFO) { printf("Device info:\n"); - plist_print_to_stream_with_indentation((plist_t)data_ptr, stdout, 2); + plist_write_to_stream((plist_t)data_ptr, stdout, PLIST_FORMAT_LIMD, PLIST_OPT_INDENT | PLIST_OPT_INDENT_BY(2)); } else if (cb_type == LOCKDOWN_CU_PAIRING_ERROR) { printf("ERROR: %s\n", (data_ptr) ? (char*)data_ptr : "(unknown)"); } @@ -257,7 +256,7 @@ int main(int argc, char **argv) goto leave; } if (*optarg == '@') { - plist_read_from_filename(&host_info_plist, optarg+1); + plist_read_from_file(optarg+1, &host_info_plist, NULL); if (!host_info_plist) { fprintf(stderr, "ERROR: Could not read from file '%s'\n", optarg+1); result = EXIT_FAILURE; diff --git a/tools/ideviceprovision.c b/tools/ideviceprovision.c index 7cd4f3f..4080a28 100644 --- a/tools/ideviceprovision.c +++ b/tools/ideviceprovision.c @@ -45,7 +45,7 @@ #include <libimobiledevice/libimobiledevice.h> #include <libimobiledevice/lockdown.h> #include <libimobiledevice/misagent.h> -#include <libimobiledevice-glue/utils.h> +#include <plist/plist.h> static void print_usage(int argc, char **argv, int is_error) { @@ -436,7 +436,7 @@ int main(int argc, char *argv[]) } } else { if (pl && (plist_get_node_type(pl) == PLIST_DICT)) { - plist_print_to_stream(pl, stdout); + plist_write_to_stream(pl, stdout, PLIST_FORMAT_LIMD, 0); } else { fprintf(stderr, "ERROR: unexpected node type in profile plist (not PLIST_DICT)\n"); res = -1; |