diff --git a/.gitignore b/.gitignore index 1d9291ace8..34a9086430 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,7 @@ www/docs/static/releases*.json *.unstripped *.bndb *.lock +*.mobileprovision internal/commands/ida/dscu/data/dscu.py internal/download/data/proto venv/ diff --git a/cmd/ipsw/cmd/appstore/appstore_profile_create.go b/cmd/ipsw/cmd/appstore/appstore_profile_create.go index 031d0d72cb..24297fedb0 100644 --- a/cmd/ipsw/cmd/appstore/appstore_profile_create.go +++ b/cmd/ipsw/cmd/appstore/appstore_profile_create.go @@ -47,12 +47,14 @@ func init() { ASProfileCreateCmd.Flags().StringP("bundle-id", "b", "", "Board ID") ASProfileCreateCmd.Flags().StringSliceP("certs", "c", []string{}, "Certificate IDs") ASProfileCreateCmd.Flags().StringSliceP("devices", "d", []string{}, "Device IDs") + ASProfileCreateCmd.Flags().Bool("offline", false, "Enable profile with 'Offline Support' (7 day validity)") ASProfileCreateCmd.Flags().StringP("output", "o", "", "Folder to download profile to") ASProfileCreateCmd.MarkFlagDirname("output") viper.BindPFlag("appstore.profile.create.type", ASProfileCreateCmd.Flags().Lookup("type")) viper.BindPFlag("appstore.profile.create.bundle-id", ASProfileCreateCmd.Flags().Lookup("bundle-id")) viper.BindPFlag("appstore.profile.create.certs", ASProfileCreateCmd.Flags().Lookup("certs")) viper.BindPFlag("appstore.profile.create.devices", ASProfileCreateCmd.Flags().Lookup("devices")) + viper.BindPFlag("appstore.profile.create.offline", ASProfileCreateCmd.Flags().Lookup("offline")) viper.BindPFlag("appstore.profile.create.output", ASProfileCreateCmd.Flags().Lookup("output")) } @@ -80,6 +82,7 @@ var ASProfileCreateCmd = &cobra.Command{ bid := viper.GetString("appstore.profile.create.bundle-id") certs := viper.GetStringSlice("appstore.profile.create.certs") devices := viper.GetStringSlice("appstore.profile.create.devices") + offline := viper.GetBool("appstore.profile.create.offline") // Validate flags if (viper.GetString("appstore.p8") == "" || viper.GetString("appstore.iss") == "" || viper.GetString("appstore.kid") == "") && viper.GetString("appstore.jwt") == "" { return fmt.Errorf("you must provide (--p8, --iss and --kid) OR --jwt") @@ -127,6 +130,9 @@ var ASProfileCreateCmd = &cobra.Command{ if err != nil { return err } + if len(cs) == 0 { + return fmt.Errorf("no certificates found") + } var choices []string for _, c := range cs { @@ -182,7 +188,7 @@ var ASProfileCreateCmd = &cobra.Command{ "devices": devices, }).Debug("Creating profile") - resp, err := as.CreateProfile(args[0], viper.GetString("appstore.profile.create.type"), bid, certs, devices) + resp, err := as.CreateProfile(args[0], viper.GetString("appstore.profile.create.type"), bid, certs, devices, offline) if err != nil { return fmt.Errorf("failed to create profile: %v", err) } diff --git a/cmd/ipsw/cmd/appstore/appstore_profile_renew.go b/cmd/ipsw/cmd/appstore/appstore_profile_renew.go index 96ad1b36cd..9bbfac45d9 100644 --- a/cmd/ipsw/cmd/appstore/appstore_profile_renew.go +++ b/cmd/ipsw/cmd/appstore/appstore_profile_renew.go @@ -158,6 +158,9 @@ var ASProfileRenewCmd = &cobra.Command{ certs = append(certs, cert.ID) } pDevs, err := as.GetProfileDevices(profile.ID) + if err != nil { + return err + } for _, dev := range pDevs { devices = append(devices, dev.ID) } @@ -173,7 +176,7 @@ var ASProfileRenewCmd = &cobra.Command{ "devices": devices, }).Debug("Creating profile") - resp, err := as.CreateProfile(profile.Attributes.Name, profile.Attributes.ProfileType, bid, certs, devices) + resp, err := as.CreateProfile(profile.Attributes.Name, string(profile.Attributes.ProfileType), bid, certs, devices, profile.Attributes.OfflineProfile) if err != nil { return fmt.Errorf("failed to create profile: %v", err) } diff --git a/pkg/appstore/cert.go b/pkg/appstore/cert.go index b25566e49f..914a52a4f5 100644 --- a/pkg/appstore/cert.go +++ b/pkg/appstore/cert.go @@ -15,45 +15,49 @@ import ( type certificateType string const ( - CT_IOS_DEVELOPMENT certificateType = "IOS_DEVELOPMENT" - CT_IOS_DISTRIBUTION certificateType = "IOS_DISTRIBUTION" - CT_MAC_APP_DISTRIBUTION certificateType = "MAC_APP_DISTRIBUTION" - CT_MAC_INSTALLER_DISTRIBUTION certificateType = "MAC_INSTALLER_DISTRIBUTION" - CT_MAC_APP_DEVELOPMENT certificateType = "MAC_APP_DEVELOPMENT" - CT_DEVELOPER_ID_KEXT certificateType = "DEVELOPER_ID_KEXT" - CT_DEVELOPER_ID_APPLICATION certificateType = "DEVELOPER_ID_APPLICATION" - CT_DEVELOPMENT certificateType = "DEVELOPMENT" - CT_DISTRIBUTION certificateType = "DISTRIBUTION" - CT_PASS_TYPE_ID certificateType = "PASS_TYPE_ID" - CT_PASS_TYPE_ID_WITH_NFC certificateType = "PASS_TYPE_ID_WITH_NFC" + CT_IOS_DEVELOPMENT certificateType = "IOS_DEVELOPMENT" + CT_IOS_DISTRIBUTION certificateType = "IOS_DISTRIBUTION" + CT_MAC_APP_DISTRIBUTION certificateType = "MAC_APP_DISTRIBUTION" + CT_MAC_INSTALLER_DISTRIBUTION certificateType = "MAC_INSTALLER_DISTRIBUTION" + CT_MAC_APP_DEVELOPMENT certificateType = "MAC_APP_DEVELOPMENT" + CT_DEVELOPER_ID_KEXT certificateType = "DEVELOPER_ID_KEXT" + CT_DEVELOPER_ID_KEXT_G2 certificateType = "DEVELOPER_ID_KEXT_G2" + CT_DEVELOPER_ID_APPLICATION certificateType = "DEVELOPER_ID_APPLICATION" + CT_DEVELOPER_ID_APPLICATION_G2 certificateType = "DEVELOPER_ID_APPLICATION_G2" + CT_DEVELOPMENT certificateType = "DEVELOPMENT" + CT_DISTRIBUTION certificateType = "DISTRIBUTION" + CT_PASS_TYPE_ID certificateType = "PASS_TYPE_ID" + CT_PASS_TYPE_ID_WITH_NFC certificateType = "PASS_TYPE_ID_WITH_NFC" ) var CertTypes = []string{ - "IOS_DEVELOPMENT", - "IOS_DISTRIBUTION", - "MAC_APP_DISTRIBUTION", - "MAC_INSTALLER_DISTRIBUTION", - "MAC_APP_DEVELOPMENT", - "DEVELOPER_ID_KEXT", - "DEVELOPER_ID_APPLICATION", - "DEVELOPMENT", - "DISTRIBUTION", - "PASS_TYPE_ID", - "PASS_TYPE_ID_WITH_NFC", + string(CT_IOS_DEVELOPMENT), + string(CT_IOS_DISTRIBUTION), + string(CT_MAC_APP_DISTRIBUTION), + string(CT_MAC_INSTALLER_DISTRIBUTION), + string(CT_MAC_APP_DEVELOPMENT), + string(CT_DEVELOPER_ID_KEXT), + string(CT_DEVELOPER_ID_KEXT_G2), + string(CT_DEVELOPER_ID_APPLICATION), + string(CT_DEVELOPER_ID_APPLICATION_G2), + string(CT_DEVELOPMENT), + string(CT_DISTRIBUTION), + string(CT_PASS_TYPE_ID), + string(CT_PASS_TYPE_ID_WITH_NFC), } type Certificate struct { - Type string `json:"type"` ID string `json:"id"` + Type string `json:"type"` Attributes struct { - SerialNumber string `json:"serialNumber"` - CertificateContent []byte `json:"certificateContent"` - DisplayName string `json:"displayName"` - Name string `json:"name"` - CsrContent any `json:"csrContent"` - Platform string `json:"platform"` - ExpirationDate Date `json:"expirationDate"` - CertificateType string `json:"certificateType"` + CertificateContent []byte `json:"certificateContent"` + DisplayName string `json:"displayName"` + ExpirationDate Date `json:"expirationDate"` + Name string `json:"name"` + Platform string `json:"platform"` + SerialNumber string `json:"serialNumber"` + CertificateType certificateType `json:"certificateType"` + CsrContent any `json:"csrContent"` } `json:"attributes"` Links Links `json:"links"` } @@ -128,10 +132,7 @@ func (as *AppStore) GetCertificates() ([]Certificate, error) { certificateDataList := make([]Certificate, 0) for _, v := range certsResp.Data { - if v.Type == "certificates" && - (v.Attributes.CertificateType == "IOS_DEVELOPMENT" || - v.Attributes.CertificateType == "MAC_APP_DEVELOPMENT" || - v.Attributes.CertificateType == "DEVELOPMENT") { + if v.Type == "certificates" { certificateDataList = append(certificateDataList, v) } } diff --git a/pkg/appstore/profile.go b/pkg/appstore/profile.go index 0e64222bea..a7218c524b 100644 --- a/pkg/appstore/profile.go +++ b/pkg/appstore/profile.go @@ -32,34 +32,35 @@ const ( ) var ProfileTypes = []string{ - "IOS_APP_DEVELOPMENT", - "IOS_APP_STORE", - "IOS_APP_ADHOC", - "IOS_APP_INHOUSE", - "MAC_APP_DEVELOPMENT", - "MAC_APP_STORE", - "MAC_APP_DIRECT", - "TVOS_APP_DEVELOPMENT", - "TVOS_APP_STORE", - "TVOS_APP_ADHOC", - "TVOS_APP_INHOUSE", - "MAC_CATALYST_APP_DEVELOPMENT", - "MAC_CATALYST_APP_STORE", - "MAC_CATALYST_APP_DIRECT", + string(IOS_APP_DEVELOPMENT), + string(IOS_APP_STORE), + string(IOS_APP_ADHOC), + string(IOS_APP_INHOUSE), + string(MAC_APP_DEVELOPMENT), + string(MAC_APP_STORE), + string(MAC_APP_DIRECT), + string(TVOS_APP_DEVELOPMENT), + string(TVOS_APP_STORE), + string(TVOS_APP_ADHOC), + string(TVOS_APP_INHOUSE), + string(MAC_CATALYST_APP_DEVELOPMENT), + string(MAC_CATALYST_APP_STORE), + string(MAC_CATALYST_APP_DIRECT), } type Profile struct { ID string `json:"id"` Type ProfileType `json:"type"` // profiles Attributes struct { - ProfileState string `json:"profileState"` - CreatedDate Date `json:"createdDate"` - ProfileType string `json:"profileType"` - Name string `json:"name"` - ProfileContent []byte `json:"profileContent"` - UUID string `json:"uuid"` - Platform string `json:"platform"` - ExpirationDate Date `json:"expirationDate"` + Name string `json:"name"` + CreatedDate Date `json:"createdDate"` + ExpirationDate Date `json:"expirationDate"` + ProfileContent []byte `json:"profileContent"` + ProfileState string `json:"profileState"` + ProfileType ProfileType `json:"profileType"` + UUID string `json:"uuid"` + Platform string `json:"platform"` + OfflineProfile bool `json:"isOfflineProfile"` } `json:"attributes"` Relationships struct { BundleID struct { @@ -116,16 +117,18 @@ func (p Profile) IsExpired() bool { } type Data struct { - ID string `json:"id"` - Type string `json:"type"` + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` } type ProfileCreateRequest struct { Data struct { Type string `json:"type"` // profiles Attributes struct { - Name string `json:"name"` - ProfileType string `json:"profileType"` + Name string `json:"name"` + ProfileType ProfileType `json:"profileType"` + TemplateName string `json:"templateName,omitempty"` + OfflineProfile bool `json:"isOfflineProfile,omitempty"` } `json:"attributes"` Relationships struct { BundleID struct { @@ -378,15 +381,16 @@ func (as *AppStore) GetProfileCerts(id string) ([]Certificate, error) { } // CreateProfile creates a new profile -func (as *AppStore) CreateProfile(name string, ptype string, bundleID string, cerIDs, devicesIDs []string) (*ProfileResponse, error) { +func (as *AppStore) CreateProfile(name string, ptype string, bundleID string, cerIDs, devicesIDs []string, offline bool) (*ProfileResponse, error) { if err := as.createToken(defaultJWTLife); err != nil { return nil, fmt.Errorf("failed to create token: %v", err) } var profileCreateRequest ProfileCreateRequest profileCreateRequest.Data.Type = "profiles" - profileCreateRequest.Data.Attributes.ProfileType = ptype profileCreateRequest.Data.Attributes.Name = name + profileCreateRequest.Data.Attributes.ProfileType = ProfileType(ptype) + profileCreateRequest.Data.Attributes.OfflineProfile = offline profileCreateRequest.Data.Relationships.BundleID.Data.Type = "bundleIds" profileCreateRequest.Data.Relationships.BundleID.Data.ID = bundleID for _, cerID := range cerIDs {