From 1aadc75eba4cc3362ffd1612765d64591ee9b7db Mon Sep 17 00:00:00 2001 From: blacktop Date: Tue, 18 Apr 2023 15:32:34 -0600 Subject: [PATCH] feat: add `ipswd` `/dsc/webkit` API route --- api/server/routes/daemon/routes.go | 2 +- api/server/routes/dsc/dsc.go | 95 ++++- api/server/routes/dsc/routes.go | 46 ++- api/server/routes/kernel/routes.go | 2 +- api/server/routes/mount/mount.go | 4 +- api/server/server.go | 2 +- api/swagger.json | 184 ++++++++- api/types/types.go | 11 +- cmd/ipsw/cmd/dyld/dyld_webkit.go | 41 +- internal/commands/dsc/dsc.go | 20 +- www/static/api/swagger.json | 622 +++++++++++++++++++++++++---- 11 files changed, 892 insertions(+), 137 deletions(-) diff --git a/api/server/routes/daemon/routes.go b/api/server/routes/daemon/routes.go index 1f4ba2034..c28f32c15 100644 --- a/api/server/routes/daemon/routes.go +++ b/api/server/routes/daemon/routes.go @@ -31,7 +31,7 @@ func AddRoutes(rg *gin.RouterGroup) { // This will return the daemon version info. rg.GET("/version", func(c *gin.Context) { c.JSON(http.StatusOK, types.Version{ - ApiVersion: api.DefaultVersion, + APIVersion: api.DefaultVersion, OSType: runtime.GOOS, BuilderVersion: types.BuildVersion, }) diff --git a/api/server/routes/dsc/dsc.go b/api/server/routes/dsc/dsc.go index ea704b763..879ba3a84 100644 --- a/api/server/routes/dsc/dsc.go +++ b/api/server/routes/dsc/dsc.go @@ -4,11 +4,20 @@ package dsc import ( "net/http" + "github.com/blacktop/go-macho" + "github.com/blacktop/ipsw/api/types" cmd "github.com/blacktop/ipsw/internal/commands/dsc" "github.com/blacktop/ipsw/pkg/dyld" "github.com/gin-gonic/gin" ) +// swagger:response +type dscImportsResponse struct { + Path string `json:"path,omitempty"` + // swagger:allOf + ImportedBy *cmd.ImportedBy `json:"imported_by,omitempty"` +} + func dscImports(c *gin.Context) { dscPath := c.Query("path") if dscPath == "" { @@ -17,18 +26,25 @@ func dscImports(c *gin.Context) { } f, err := dyld.Open(dscPath) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } defer f.Close() imps, err := cmd.GetDylibsThatImport(f, c.Query("dylib")) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } - c.IndentedJSON(http.StatusOK, gin.H{"path": dscPath, "imported_by": imps}) + c.IndentedJSON(http.StatusOK, dscImportsResponse{Path: dscPath, ImportedBy: imps}) +} + +// swagger:response +type dscInfoResponse struct { + Path string `json:"path,omitempty"` + // swagger:allOf + Info *cmd.Info `json:"info,omitempty"` } func dscInfo(c *gin.Context) { @@ -39,49 +55,63 @@ func dscInfo(c *gin.Context) { } f, err := dyld.Open(dscPath) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } defer f.Close() info, err := cmd.GetInfo(f) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } - c.IndentedJSON(http.StatusOK, gin.H{"path": dscPath, "info": info}) + c.IndentedJSON(http.StatusOK, dscInfoResponse{Path: dscPath, Info: info}) +} + +// swagger:response +type dscMachoResponse struct { + Path string `json:"path,omitempty"` + // swagger:allOf + Macho *macho.File `json:"macho,omitempty"` } func dscMacho(c *gin.Context) { dscPath := c.Query("path") f, err := dyld.Open(dscPath) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } defer f.Close() image, err := f.Image(c.Query("dylib")) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } m, err := image.GetMacho() if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } - c.IndentedJSON(http.StatusOK, gin.H{"path": dscPath, "macho": m}) + c.IndentedJSON(http.StatusOK, dscMachoResponse{Path: dscPath, Macho: m}) +} + +// swagger:response +type dscStringsResponse struct { + Path string `json:"path,omitempty"` + // swagger:allOf + Strings []cmd.String `json:"strings,omitempty"` } func dscStrings(c *gin.Context) { dscPath := c.Query("path") f, err := dyld.Open(dscPath) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } defer f.Close() @@ -89,33 +119,64 @@ func dscStrings(c *gin.Context) { pattern := c.Query("pattern") strs, err := cmd.GetStrings(f, pattern) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } - c.IndentedJSON(http.StatusOK, gin.H{"path": dscPath, "strings": strs}) + c.IndentedJSON(http.StatusOK, dscStringsResponse{Path: dscPath, Strings: strs}) +} + +// swagger:response +type dscSymbolsResponse struct { + Path string `json:"path,omitempty"` + // swagger:allOf + Symbols []cmd.Symbol `json:"symbols,omitempty"` } func dscSymbols(c *gin.Context) { dscPath := c.Query("path") f, err := dyld.Open(dscPath) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } defer f.Close() var lookups []cmd.Symbol if err := c.ShouldBindJSON(&lookups); err != nil { - c.AbortWithError(http.StatusBadRequest, err) + c.AbortWithStatusJSON(http.StatusBadRequest, types.GenericError{Error: err.Error()}) return } syms, err := cmd.GetSymbols(f, lookups) if err != nil { - c.AbortWithError(http.StatusInternalServerError, err) + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) return } - c.IndentedJSON(http.StatusOK, gin.H{"path": dscPath, "symbols": syms}) + c.IndentedJSON(http.StatusOK, dscSymbolsResponse{Path: dscPath, Symbols: syms}) +} + +// swagger:response +type dscWebkitResponse struct { + Path string `json:"path,omitempty"` + Webkit string `json:"webkit,omitempty"` +} + +func dscWebkit(c *gin.Context) { + dscPath := c.Query("path") + f, err := dyld.Open(dscPath) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) + return + } + defer f.Close() + + version, err := cmd.GetWebkitVersion(f) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, types.GenericError{Error: err.Error()}) + return + } + + c.IndentedJSON(http.StatusOK, dscWebkitResponse{Path: dscPath, Webkit: version}) } diff --git a/api/server/routes/dsc/routes.go b/api/server/routes/dsc/routes.go index 0e8c9aa5a..7c7bc53d0 100644 --- a/api/server/routes/dsc/routes.go +++ b/api/server/routes/dsc/routes.go @@ -37,6 +37,9 @@ func AddRoutes(rg *gin.RouterGroup) { // description: dylib to search for // required: true // type: string + // Responses: + // 200: dscImportsResponse + // 500: genericError dr.GET("/imports", dscImports) // swagger:route GET /dsc/info DSC getDscInfo // @@ -53,6 +56,9 @@ func AddRoutes(rg *gin.RouterGroup) { // description: path to dyld_shared_cache // required: true // type: string + // Responses: + // 200: dscInfoResponse + // 500: genericError dr.GET("/info", dscInfo) // swagger:route GET /dsc/macho DSC getDscMacho // @@ -74,6 +80,9 @@ func AddRoutes(rg *gin.RouterGroup) { // description: dylib to search for // required: true // type: string + // Responses: + // 200: dscMachoResponse + // 500: genericError dr.GET("/macho", dscMacho) // dr.GET("/o2a", handler) // TODO: implement this // dr.GET("/objc", handler) // TODO: implement this @@ -102,6 +111,9 @@ func AddRoutes(rg *gin.RouterGroup) { // description: regex to search for // required: true // type: string + // Responses: + // 200: dscStringsResponse + // 500: genericError dr.GET("/str", dscStrings) // dr.GET("/stubs", handler) // TODO: implement this // dr.GET("/swift", handler) // TODO: implement this @@ -131,8 +143,40 @@ func AddRoutes(rg *gin.RouterGroup) { // description: path to dyld_shared_cache // required: true // type: string + // responses: + // '200': + // description: symbol lookup response + // schema: + // $ref: '#/responses/dscSymbolsResponse' + // '400': + // description: bad request + // schema: + // $ref: '#/responses/genericError' + // '500': + // description: error + // schema: + // $ref: '#/responses/genericError' dr.POST("/symaddr", dscSymbols) // dr.GET("/tbd", handler) // TODO: implement this - // dr.GET("/webkit", handler) // TODO: implement this + + // swagger:route GET /dsc/webkit DSC getDscWebkit + // + // Webkit + // + // Get webkit version from dylib in the DSC. + // + // Produces: + // - application/json + // + // Parameters: + // + name: path + // in: query + // description: path to dyld_shared_cache + // required: true + // type: string + // Responses: + // 200: dscWebkitResponse + // 500: genericError + dr.GET("/webkit", dscWebkit) // TODO: implement this // dr.GET("/xref", handler) // TODO: implement this } diff --git a/api/server/routes/kernel/routes.go b/api/server/routes/kernel/routes.go index 927bbfd09..577281b8c 100644 --- a/api/server/routes/kernel/routes.go +++ b/api/server/routes/kernel/routes.go @@ -64,7 +64,7 @@ func AddRoutes(rg *gin.RouterGroup) { // required: true // type: string // Responses: - // default: genericError + // 500: genericError // 200: kernelcacheVersion kg.GET("/version", getVersion) } diff --git a/api/server/routes/mount/mount.go b/api/server/routes/mount/mount.go index f93fe95c4..0c44c95cc 100644 --- a/api/server/routes/mount/mount.go +++ b/api/server/routes/mount/mount.go @@ -43,7 +43,7 @@ func AddRoutes(rg *gin.RouterGroup) { // required: true // type: string // Responses: - // default: genericError + // 500: genericError // 200: mountReponse rg.POST("/mount/:type", func(c *gin.Context) { ipswPath := filepath.Clean(c.Query("path")) @@ -80,7 +80,7 @@ func AddRoutes(rg *gin.RouterGroup) { // description: path to DMG // type: string // Responses: - // default: genericError + // 500: genericError // 200: successResponse rg.POST("/unmount", func(c *gin.Context) { ctx := mount.Context{} diff --git a/api/server/server.go b/api/server/server.go index cdcdf05db..a945bc40a 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -77,7 +77,7 @@ func (s *Server) Start() error { s.router.GET("/version", func(c *gin.Context) { c.JSON(http.StatusOK, types.Version{ - ApiVersion: api.DefaultVersion, + APIVersion: api.DefaultVersion, OSType: runtime.GOOS, BuilderVersion: types.BuildVersion, }) diff --git a/api/swagger.json b/api/swagger.json index 15c531884..0d60dedfa 100644 --- a/api/swagger.json +++ b/api/swagger.json @@ -94,7 +94,15 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscImportsResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/info": { @@ -116,7 +124,15 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscInfoResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/macho": { @@ -145,7 +161,15 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscMachoResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/str": { @@ -174,7 +198,15 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscStringsResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/symaddr": { @@ -211,7 +243,57 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "description": "symbol lookup response", + "schema": { + "$ref": "#/responses/dscSymbolsResponse" + } + }, + "400": { + "description": "bad request", + "schema": { + "$ref": "#/responses/genericError" + } + }, + "500": { + "description": "error", + "schema": { + "$ref": "#/responses/genericError" + } + } + } + } + }, + "/dsc/webkit": { + "get": { + "description": "Get \u003ccode\u003ewebkit\u003c/code\u003e version from dylib in the DSC.", + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], + "summary": "Webkit", + "operationId": "getDscWebkit", + "parameters": [ + { + "type": "string", + "description": "path to dyld_shared_cache", + "name": "path", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/dscWebkitResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/extract/dmg": { @@ -765,7 +847,7 @@ "200": { "$ref": "#/responses/kernelcacheVersion" }, - "default": { + "500": { "$ref": "#/responses/genericError" } } @@ -830,7 +912,7 @@ "200": { "$ref": "#/responses/mountReponse" }, - "default": { + "500": { "$ref": "#/responses/genericError" } } @@ -866,7 +948,7 @@ "200": { "$ref": "#/responses/successResponse" }, - "default": { + "500": { "$ref": "#/responses/genericError" } } @@ -884,6 +966,18 @@ } }, "definitions": { + "Dylib": { + "description": "Dylib is a struct that contains information about a dyld_shared_cache dylib", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "ImportedBy": { + "description": "ImportedBy is a struct that contains information about which dyld_shared_cache dylibs import a given dylib", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "Info": { + "description": "Info is a struct that contains information about a dyld_shared_cache file", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, "KernelVersion": { "title": "KernelVersion represents the kernel version.", "x-go-package": "github.com/blacktop/ipsw/pkg/kernelcache" @@ -892,12 +986,78 @@ "title": "LLVMVersion represents the LLVM version used to compile the kernel.", "x-go-package": "github.com/blacktop/ipsw/pkg/kernelcache" }, + "String": { + "description": "String is a struct that contains information about a dyld_shared_cache string", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, "Symbol": { "description": "Symbol is a struct that contains information about a dyld_shared_cache symbol", "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" } }, "responses": { + "dscImportsResponse": { + "description": "", + "headers": { + "imported_by": {}, + "path": { + "type": "string" + } + } + }, + "dscInfoResponse": { + "description": "", + "headers": { + "info": {}, + "path": { + "type": "string" + } + } + }, + "dscMachoResponse": { + "description": "", + "headers": { + "macho": {}, + "path": { + "type": "string" + } + } + }, + "dscStringsResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "strings": { + "type": "array", + "items": {} + } + } + }, + "dscSymbolsResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "symbols": { + "type": "array", + "items": {} + } + } + }, + "dscWebkitResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "webkit": { + "type": "string" + } + } + }, "extractReponse": { "description": "The extract response message", "schema": { @@ -907,6 +1067,14 @@ } } }, + "genericError": { + "description": "", + "headers": { + "error": { + "type": "string" + } + } + }, "kernelcacheVersion": { "description": "Version represents the kernel version and LLVM version.", "headers": { diff --git a/api/types/types.go b/api/types/types.go index d1ed8c5f0..ebbcfe16c 100644 --- a/api/types/types.go +++ b/api/types/types.go @@ -7,7 +7,12 @@ var ( // Version is the version struct type Version struct { - ApiVersion string - OSType string - BuilderVersion string + APIVersion string `json:"api_version,omitempty"` + OSType string `json:"os_type,omitempty"` + BuilderVersion string `json:"builder_version,omitempty"` +} + +// swagger:response genericError +type GenericError struct { + Error string `json:"error"` } diff --git a/cmd/ipsw/cmd/dyld/dyld_webkit.go b/cmd/ipsw/cmd/dyld/dyld_webkit.go index 775034b7e..f0cd87959 100644 --- a/cmd/ipsw/cmd/dyld/dyld_webkit.go +++ b/cmd/ipsw/cmd/dyld/dyld_webkit.go @@ -29,6 +29,7 @@ import ( "strings" "github.com/apex/log" + dcsCmd "github.com/blacktop/ipsw/internal/commands/dsc" "github.com/blacktop/ipsw/internal/download" "github.com/blacktop/ipsw/internal/utils" "github.com/blacktop/ipsw/pkg/dyld" @@ -105,14 +106,9 @@ var WebkitCmd = &cobra.Command{ } defer f.Close() - image, err := f.Image("WebKit") + webkit1, err := dcsCmd.GetWebkitVersion(f) if err != nil { - return fmt.Errorf("image not in %s: %v", dscPath, err) - } - - m, err := image.GetPartialMacho() - if err != nil { - return err + return fmt.Errorf("failed to get WebKit version: %v", err) } if diff { @@ -140,19 +136,14 @@ var WebkitCmd = &cobra.Command{ } defer f.Close() - image, err := f.Image("WebKit") + webkit2, err := dcsCmd.GetWebkitVersion(f) if err != nil { - return fmt.Errorf("image not in %s: %v", dscPath2, err) - } - - m2, err := image.GetPartialMacho() - if err != nil { - return err + return fmt.Errorf("failed to get WebKit version: %v", err) } out, err := utils.GitDiff( - m.SourceVersion().Version.String()+"\n", - m2.SourceVersion().Version.String()+"\n", + webkit1+"\n", + webkit2+"\n", &utils.GitDiffConfig{Color: viper.GetBool("color"), Tool: viper.GetString("diff-tool")}) if err != nil { return err @@ -170,9 +161,9 @@ var WebkitCmd = &cobra.Command{ var svnRev string if getRev { log.Info("Querying https://trac.webkit.org...") - ver, rev, err := dyld.ScrapeWebKitTRAC(m.SourceVersion().Version.String()) + ver, rev, err := dyld.ScrapeWebKitTRAC(webkit1) if err != nil { - log.Infof("WebKit Version: %s", m.SourceVersion().Version) + log.Infof("WebKit Version: %s", webkit1) return err } svnRev = fmt.Sprintf("%s (svn rev %s)", ver, rev) @@ -182,24 +173,24 @@ var WebkitCmd = &cobra.Command{ if len(apiToken) == 0 { tags, err = download.GetPreprocessedWebKitTags(proxy, insecure) if err != nil { - log.Infof("WebKit Version: %s", m.SourceVersion().Version) + log.Infof("WebKit Version: %s", webkit1) return err } } else { tags, err = download.WebKitGraphQLTags(proxy, insecure, apiToken) if err != nil { - log.Infof("WebKit Version: %s", m.SourceVersion().Version) + log.Infof("WebKit Version: %s", webkit1) return err } } for _, tag := range tags { - if strings.Contains(tag.Name, m.SourceVersion().Version.String()) { + if strings.Contains(tag.Name, webkit1) { if asJSON { b, err := json.Marshal(&struct { Version string `json:"version"` Tag download.GithubTag `json:"tag,omitempty"` }{ - Version: m.SourceVersion().Version.String(), + Version: webkit1, Tag: tag, }) if err != nil { @@ -207,7 +198,7 @@ var WebkitCmd = &cobra.Command{ } fmt.Println(string(b)) } else { - log.Infof("WebKit Version: %s", m.SourceVersion().Version) + log.Infof("WebKit Version: %s", webkit1) utils.Indent(log.Info, 2)(fmt.Sprintf("Tag: %s", tag.Name)) utils.Indent(log.Info, 2)(fmt.Sprintf("URL: %s", tag.TarURL)) utils.Indent(log.Info, 2)(fmt.Sprintf("Date: %s", tag.Commit.Date.Format("02Jan2006 15:04:05"))) @@ -222,7 +213,7 @@ var WebkitCmd = &cobra.Command{ Version string `json:"version"` Rev string `json:"rev,omitempty"` }{ - Version: m.SourceVersion().Version.String(), + Version: webkit1, Rev: svnRev, }) if err != nil { @@ -230,7 +221,7 @@ var WebkitCmd = &cobra.Command{ } fmt.Println(string(b)) } else { - log.Infof("WebKit Version: %s", m.SourceVersion().Version) + log.Infof("WebKit Version: %s", webkit1) if len(svnRev) > 0 { utils.Indent(log.Info, 2)(svnRev) } diff --git a/internal/commands/dsc/dsc.go b/internal/commands/dsc/dsc.go index 46414c2ee..d753e159e 100644 --- a/internal/commands/dsc/dsc.go +++ b/internal/commands/dsc/dsc.go @@ -15,12 +15,14 @@ import ( ) // ImportedBy is a struct that contains information about which dyld_shared_cache dylibs import a given dylib +// swagger:model type ImportedBy struct { DSC []string `json:"dsc,omitempty"` Apps []string `json:"apps,omitempty"` } // Dylib is a struct that contains information about a dyld_shared_cache dylib +// swagger:model type Dylib struct { Index int `json:"index,omitempty"` Name string `json:"name,omitempty"` @@ -30,6 +32,7 @@ type Dylib struct { } // Info is a struct that contains information about a dyld_shared_cache file +// swagger:model type Info struct { Magic string `json:"magic,omitempty"` UUID string `json:"uuid,omitempty"` @@ -44,7 +47,6 @@ type Info struct { } // Symbol is a struct that contains information about a dyld_shared_cache symbol -// // swagger:model type Symbol struct { // The address of the symbol @@ -62,6 +64,7 @@ type Symbol struct { } // String is a struct that contains information about a dyld_shared_cache string +// swagger:model type String struct { Address uint64 `json:"address,omitempty"` Image string `json:"image,omitempty"` @@ -365,3 +368,18 @@ func GetStrings(f *dyld.File, pattern string) ([]String, error) { return strs, nil } + +// GetWebkitVersion returns the WebKit version from a dyld_shared_cache file +func GetWebkitVersion(f *dyld.File) (string, error) { + image, err := f.Image("WebKit") + if err != nil { + return "", fmt.Errorf("image not in DSC: %v", err) + } + + m, err := image.GetPartialMacho() + if err != nil { + return "", fmt.Errorf("failed to create MachO for image %s: %v", image.Name, err) + } + + return m.SourceVersion().Version.String(), nil +} diff --git a/www/static/api/swagger.json b/www/static/api/swagger.json index 366fedbc0..0d60dedfa 100644 --- a/www/static/api/swagger.json +++ b/www/static/api/swagger.json @@ -1,7 +1,13 @@ { - "consumes": ["application/json"], - "produces": ["application/json"], - "schemes": ["http"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "http" + ], "swagger": "2.0", "info": { "description": "This allows you to interact with \u003ccode\u003eipsw\u003c/code\u003e in a VERY powerful and flexible way via a RESTful API.\n\nThe \u003ccode\u003eipswd\u003c/code\u003e design was heavily influenced by the design of dockerd. So many of the same concepts apply.", @@ -14,13 +20,17 @@ "/_ping": { "get": { "description": "This will return \"OK\" if the daemon is running.", - "tags": ["Daemon"], + "tags": [ + "Daemon" + ], "summary": "Ping", "operationId": "getDaemonPing" }, "head": { "description": "This will return if 200 the daemon is running.", - "tags": ["Daemon"], + "tags": [ + "Daemon" + ], "summary": "Ping", "operationId": "headDaemonPing" } @@ -28,8 +38,12 @@ "/device_list": { "get": { "description": "This will return JSON of all XCode devices.", - "produces": ["application/json"], - "tags": ["DeviceList"], + "produces": [ + "application/json" + ], + "tags": [ + "DeviceList" + ], "summary": "List XCode Devices.", "operationId": "getDeviceList" } @@ -37,7 +51,9 @@ "/download/ipsw/ios/latest/build": { "get": { "description": "Get latest iOS build.", - "tags": ["Download"], + "tags": [ + "Download" + ], "summary": "Latest iOS Build", "operationId": "getDownloadLatestIPSWsBuild" } @@ -45,7 +61,9 @@ "/download/ipsw/ios/latest/version": { "get": { "description": "Get latest iOS version.", - "tags": ["Download"], + "tags": [ + "Download" + ], "summary": "Latest iOS Version", "operationId": "getDownloadLatestIPSWsVersion" } @@ -53,8 +71,12 @@ "/dsc/imports": { "get": { "description": "Get list of dylibs that import a given dylib.", - "produces": ["application/json"], - "tags": ["DSC"], + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], "summary": "Imports", "operationId": "getDscImports", "parameters": [ @@ -72,14 +94,26 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscImportsResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/info": { "get": { "description": "Get info about a given DSC", - "produces": ["application/json"], - "tags": ["DSC"], + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], "summary": "Info", "operationId": "getDscInfo", "parameters": [ @@ -90,14 +124,26 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscInfoResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/macho": { "get": { "description": "Get MachO info for a given dylib in the DSC.", - "produces": ["application/json"], - "tags": ["DSC"], + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], "summary": "MachO", "operationId": "getDscMacho", "parameters": [ @@ -115,14 +161,26 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscMachoResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/str": { "get": { "description": "Get strings in the DSC that match a given pattern.", - "produces": ["application/json"], - "tags": ["DSC"], + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], "summary": "Strings", "operationId": "getDscStrings", "parameters": [ @@ -140,17 +198,85 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscStringsResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/dsc/symaddr": { "get": { "description": "Get symbols addresses in the DSC that match a given lookup JSON payload.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["DSC"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], "summary": "Symbols", "operationId": "getDscSymbols", + "parameters": [ + { + "description": "Symbol lookups", + "name": "lookups", + "in": "body", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Symbol" + } + } + }, + { + "type": "string", + "description": "path to dyld_shared_cache", + "name": "path", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "symbol lookup response", + "schema": { + "$ref": "#/responses/dscSymbolsResponse" + } + }, + "400": { + "description": "bad request", + "schema": { + "$ref": "#/responses/genericError" + } + }, + "500": { + "description": "error", + "schema": { + "$ref": "#/responses/genericError" + } + } + } + } + }, + "/dsc/webkit": { + "get": { + "description": "Get \u003ccode\u003ewebkit\u003c/code\u003e version from dylib in the DSC.", + "produces": [ + "application/json" + ], + "tags": [ + "DSC" + ], + "summary": "Webkit", + "operationId": "getDscWebkit", "parameters": [ { "type": "string", @@ -159,15 +285,29 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/dscWebkitResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/extract/dmg": { "post": { "description": "Extract DMGs from an IPSW.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["Extract"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Extract" + ], "summary": "DMG", "operationId": "getExtractDmg", "parameters": [ @@ -204,15 +344,29 @@ } } } - ] + ], + "responses": { + "200": { + "description": "extraction response", + "schema": { + "$ref": "#/responses/extractReponse" + } + } + } } }, "/extract/dsc": { "post": { "description": "Extract dyld_shared_caches from an IPSW.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["Extract"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Extract" + ], "summary": "DSC", "operationId": "getExtractDsc", "parameters": [ @@ -252,15 +406,29 @@ } } } - ] + ], + "responses": { + "200": { + "description": "extraction response", + "schema": { + "$ref": "#/responses/extractReponse" + } + } + } } }, "/extract/kbag": { "post": { "description": "Extract KBAGs from an IPSW.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["Extract"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Extract" + ], "summary": "KBAG", "operationId": "getExtractKbags", "parameters": [ @@ -296,15 +464,29 @@ } } } - ] + ], + "responses": { + "200": { + "description": "extraction response", + "schema": { + "$ref": "#/responses/extractReponse" + } + } + } } }, "/extract/kernel": { "post": { "description": "Extract kernelcaches from an IPSW.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["Extract"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Extract" + ], "summary": "Kernel", "operationId": "getExtractKernel", "parameters": [ @@ -337,15 +519,29 @@ } } } - ] + ], + "responses": { + "200": { + "description": "extraction response", + "schema": { + "$ref": "#/responses/extractReponse" + } + } + } } }, "/extract/pattern": { "post": { "description": "Extract files from an IPSW that match a given pattern.", - "consumes": ["application/json"], - "produces": ["application/json"], - "tags": ["Extract"], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Extract" + ], "summary": "Pattern", "operationId": "getExtractPattern", "parameters": [ @@ -384,13 +580,23 @@ } } } - ] + ], + "responses": { + "200": { + "description": "extraction response", + "schema": { + "$ref": "#/responses/extractReponse" + } + } + } } }, "/idev/info": { "get": { "description": "Get info about USB connected devices.", - "tags": ["USB"], + "tags": [ + "USB" + ], "summary": "Info", "operationId": "getIdevInfo" } @@ -398,8 +604,12 @@ "/info/ipsw": { "get": { "description": "Get IPSW info.", - "produces": ["application/json"], - "tags": ["Info"], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], "summary": "IPSW", "operationId": "getIpswInfo", "parameters": [ @@ -416,8 +626,12 @@ "/info/ipsw/remote": { "get": { "description": "Get remote IPSW info.", - "produces": ["application/json"], - "tags": ["Info"], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], "summary": "Remote IPSW", "operationId": "getRemoteIpswInfo", "parameters": [ @@ -446,8 +660,12 @@ "/info/ota": { "get": { "description": "Get OTA info.", - "produces": ["application/json"], - "tags": ["Info"], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], "summary": "OTA", "operationId": "getOtaInfo", "parameters": [ @@ -464,8 +682,12 @@ "/info/ota/remote": { "get": { "description": "Get remote OTA info.", - "produces": ["application/json"], - "tags": ["Info"], + "produces": [ + "application/json" + ], + "tags": [ + "Info" + ], "summary": "Remote OTA", "operationId": "getRemoteOtaInfo", "parameters": [ @@ -494,8 +716,12 @@ "/ipsw/fs/ents": { "get": { "description": "Get IPSW Filesystem DMG MachO entitlements.", - "produces": ["application/json"], - "tags": ["IPSW"], + "produces": [ + "application/json" + ], + "tags": [ + "IPSW" + ], "summary": "Entitlements", "operationId": "getIpswFsEntitlements", "parameters": [ @@ -512,8 +738,12 @@ "/ipsw/fs/files": { "get": { "description": "Get IPSW Filesystem DMG file listing.", - "produces": ["application/json"], - "tags": ["IPSW"], + "produces": [ + "application/json" + ], + "tags": [ + "IPSW" + ], "summary": "Files", "operationId": "getIpswFsFiles", "parameters": [ @@ -530,8 +760,12 @@ "/ipsw/fs/launchd": { "get": { "description": "Get \u003ccode\u003elaunchd\u003c/code\u003e config from IPSW Filesystem DMG.", - "produces": ["application/json"], - "tags": ["IPSW"], + "produces": [ + "application/json" + ], + "tags": [ + "IPSW" + ], "summary": "launchd Config", "operationId": "getIpswFsLaunchd", "parameters": [ @@ -548,8 +782,12 @@ "/kernel/kexts": { "get": { "description": "Get kernelcache KEXTs info.", - "produces": ["application/json"], - "tags": ["Kernel"], + "produces": [ + "application/json" + ], + "tags": [ + "Kernel" + ], "summary": "Kexts", "operationId": "getKernelKexts", "parameters": [ @@ -566,8 +804,12 @@ "/kernel/syscall": { "get": { "description": "Get kernelcache syscalls info.", - "produces": ["application/json"], - "tags": ["Kernel"], + "produces": [ + "application/json" + ], + "tags": [ + "Kernel" + ], "summary": "Syscalls", "operationId": "getKernelSyscalls", "parameters": [ @@ -584,8 +826,12 @@ "/kernel/version": { "get": { "description": "Get kernelcache version.", - "produces": ["application/json"], - "tags": ["Kernel"], + "produces": [ + "application/json" + ], + "tags": [ + "Kernel" + ], "summary": "Version", "operationId": "getKernelVersion", "parameters": [ @@ -596,14 +842,26 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/kernelcacheVersion" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/macho/info": { "get": { "description": "Get MachO info.", - "produces": ["application/json"], - "tags": ["MachO"], + "produces": [ + "application/json" + ], + "tags": [ + "MachO" + ], "summary": "Info", "operationId": "getMachoInfo", "parameters": [ @@ -626,8 +884,12 @@ "/mount/{type}": { "post": { "description": "Mount a DMG inside a given IPSW.", - "produces": ["application/json"], - "tags": ["Mount"], + "produces": [ + "application/json" + ], + "tags": [ + "Mount" + ], "summary": "Mount", "operationId": "postMount", "parameters": [ @@ -645,14 +907,26 @@ "in": "query", "required": true } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/mountReponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/unmount": { "post": { "description": "Unmount a previously mounted DMG.", - "produces": ["application/json"], - "tags": ["Mount"], + "produces": [ + "application/json" + ], + "tags": [ + "Mount" + ], "summary": "Unmount", "operationId": "postUnmount", "parameters": [ @@ -669,16 +943,210 @@ "name": "dmg_path", "in": "query" } - ] + ], + "responses": { + "200": { + "$ref": "#/responses/successResponse" + }, + "500": { + "$ref": "#/responses/genericError" + } + } } }, "/version": { "get": { "description": "This will return the daemon version info.", - "tags": ["Daemon"], + "tags": [ + "Daemon" + ], "summary": "Version", "operationId": "getDaemonVersion" } } + }, + "definitions": { + "Dylib": { + "description": "Dylib is a struct that contains information about a dyld_shared_cache dylib", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "ImportedBy": { + "description": "ImportedBy is a struct that contains information about which dyld_shared_cache dylibs import a given dylib", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "Info": { + "description": "Info is a struct that contains information about a dyld_shared_cache file", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "KernelVersion": { + "title": "KernelVersion represents the kernel version.", + "x-go-package": "github.com/blacktop/ipsw/pkg/kernelcache" + }, + "LLVMVersion": { + "title": "LLVMVersion represents the LLVM version used to compile the kernel.", + "x-go-package": "github.com/blacktop/ipsw/pkg/kernelcache" + }, + "String": { + "description": "String is a struct that contains information about a dyld_shared_cache string", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + }, + "Symbol": { + "description": "Symbol is a struct that contains information about a dyld_shared_cache symbol", + "x-go-package": "github.com/blacktop/ipsw/internal/commands/dsc" + } + }, + "responses": { + "dscImportsResponse": { + "description": "", + "headers": { + "imported_by": {}, + "path": { + "type": "string" + } + } + }, + "dscInfoResponse": { + "description": "", + "headers": { + "info": {}, + "path": { + "type": "string" + } + } + }, + "dscMachoResponse": { + "description": "", + "headers": { + "macho": {}, + "path": { + "type": "string" + } + } + }, + "dscStringsResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "strings": { + "type": "array", + "items": {} + } + } + }, + "dscSymbolsResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "symbols": { + "type": "array", + "items": {} + } + } + }, + "dscWebkitResponse": { + "description": "", + "headers": { + "path": { + "type": "string" + }, + "webkit": { + "type": "string" + } + } + }, + "extractReponse": { + "description": "The extract response message", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "genericError": { + "description": "", + "headers": { + "error": { + "type": "string" + } + } + }, + "kernelcacheVersion": { + "description": "Version represents the kernel version and LLVM version.", + "headers": { + "arch": { + "type": "string", + "description": "The kernel architecture" + }, + "clang": { + "type": "string", + "description": "The LLVM compiler" + }, + "cpu": { + "type": "string", + "description": "The kernel CPU" + }, + "darwin": { + "type": "string", + "description": "The darwin version" + }, + "date": { + "type": "string", + "format": "date-time", + "description": "The build date" + }, + "flags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The LLVM compiler flags" + }, + "rawKernel": { + "type": "string" + }, + "rawLLVM": { + "type": "string" + }, + "type": { + "type": "string", + "description": "The kernel type" + }, + "version": { + "type": "string", + "description": "The LLVM version" + }, + "xnu": { + "type": "string", + "description": "The xnu version" + } + } + }, + "mountReponse": { + "description": "", + "headers": { + "already_mounted": { + "type": "boolean" + }, + "dmg_path": { + "type": "string" + }, + "mount_point": { + "type": "string" + } + } + }, + "successResponse": { + "description": "", + "headers": { + "success": { + "type": "boolean" + } + } + } } -} +} \ No newline at end of file