mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-14 01:35:55 +09:00
Add support for ssh commit signing (#17743)
* Add support for ssh commit signing * Split out ssh verification to separate file * Show ssh key fingerprint on commit page * Update sshsig lib * Make sure we verify against correct namespace * Add ssh public key verification via ssh signatures When adding a public ssh key also validate that this user actually owns the key by signing a token with the private key. * Remove some gpg references and make verify key optional * Fix spaces indentation * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update templates/user/settings/keys_ssh.tmpl Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update options/locale/locale_en-US.ini Co-authored-by: Gusted <williamzijl7@hotmail.com> * Update models/ssh_key_commit_verification.go Co-authored-by: Gusted <williamzijl7@hotmail.com> * Reword ssh/gpg_key_success message * Change Badsignature to NoKeyFound * Add sign/verify tests * Fix upstream api changes to user_model User * Match exact on SSH signature * Fix code review remarks Co-authored-by: Gusted <williamzijl7@hotmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
182 files changed
+17554
-15288
No files matched your search
@@ -11,6 +11,7 @@ require (
|
||||
gitea.com/go-chi/captcha v0.0.0-20211013065431-70641c1a35d5
|
||||
gitea.com/go-chi/session v0.0.0-20211013065435-7d334f340c09
|
||||
gitea.com/lunny/levelqueue v0.4.1
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/ProtonMail/go-crypto v0.0.0-20210705153151-cc34b1f6908b // indirect
|
||||
@@ -121,10 +122,10 @@ require (
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.7.0 // indirect
|
||||
go.uber.org/zap v1.19.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2
|
||||
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1
|
||||
golang.org/x/text v0.3.7
|
||||
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirect
|
||||
golang.org/x/tools v0.1.0
|
||||
|
||||
@@ -54,6 +54,8 @@ gitea.com/lunny/levelqueue v0.4.1 h1:RZ+AFx5gBsZuyqCvofhAkPQ9uaVDPJnsULoJZIYaJNw
|
||||
gitea.com/lunny/levelqueue v0.4.1/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 h1:r3qt8PCHnfjOv9PN3H+XXKmDA1dfFMIN1AislhlA/ps=
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121/go.mod h1:Ock8XgA7pvULhIaHGAk/cDnRfNrF9Jey81nPcc403iU=
|
||||
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U=
|
||||
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
|
||||
@@ -1261,6 +1263,8 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -1355,6 +1359,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c=
|
||||
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1462,6 +1468,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
@@ -246,3 +246,19 @@ func IsErrDeployKeyNameAlreadyUsed(err error) bool {
|
||||
func (err ErrDeployKeyNameAlreadyUsed) Error() string {
|
||||
return fmt.Sprintf("public key with name already exists [repo_id: %d, name: %s]", err.RepoID, err.Name)
|
||||
}
|
||||
|
||||
// ErrSSHInvalidTokenSignature represents a "ErrSSHInvalidTokenSignature" kind of error.
|
||||
type ErrSSHInvalidTokenSignature struct {
|
||||
Wrapped error
|
||||
Fingerprint string
|
||||
}
|
||||
|
||||
// IsErrSSHInvalidTokenSignature checks if an error is a ErrSSHInvalidTokenSignature.
|
||||
func IsErrSSHInvalidTokenSignature(err error) bool {
|
||||
_, ok := err.(ErrSSHInvalidTokenSignature)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrSSHInvalidTokenSignature) Error() string {
|
||||
return "the provided signature does not sign the token with the provided key"
|
||||
}
|
||||
@@ -49,6 +49,7 @@ type CommitVerification struct {
|
||||
CommittingUser *user_model.User
|
||||
SigningEmail string
|
||||
SigningKey *GPGKey
|
||||
SigningSSHKey *PublicKey
|
||||
TrustStatus string
|
||||
}
|
||||
|
||||
@@ -122,6 +123,11 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
|
||||
}
|
||||
}
|
||||
|
||||
// If this a SSH signature handle it differently
|
||||
if strings.HasPrefix(c.Signature.Signature, "-----BEGIN SSH SIGNATURE-----") {
|
||||
return ParseCommitWithSSHSignature(c, committer)
|
||||
}
|
||||
|
||||
// Parsing signature
|
||||
sig, err := extractSignature(c.Signature.Signature)
|
||||
if err != nil { // Skipping failed to extract sign
|
||||
@@ -487,28 +493,31 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
|
||||
return
|
||||
}
|
||||
|
||||
var isMember bool
|
||||
if keyMap != nil {
|
||||
var has bool
|
||||
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
|
||||
if !has {
|
||||
// Check we actually have a GPG SigningKey
|
||||
if verification.SigningKey != nil {
|
||||
var isMember bool
|
||||
if keyMap != nil {
|
||||
var has bool
|
||||
isMember, has = (*keyMap)[verification.SigningKey.KeyID]
|
||||
if !has {
|
||||
isMember, err = isCodeReader(verification.SigningUser)
|
||||
(*keyMap)[verification.SigningKey.KeyID] = isMember
|
||||
}
|
||||
} else {
|
||||
isMember, err = isCodeReader(verification.SigningUser)
|
||||
(*keyMap)[verification.SigningKey.KeyID] = isMember
|
||||
}
|
||||
} else {
|
||||
isMember, err = isCodeReader(verification.SigningUser)
|
||||
}
|
||||
|
||||
if !isMember {
|
||||
verification.TrustStatus = "untrusted"
|
||||
if verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
// The committing user and the signing user are not the same
|
||||
// This should be marked as questionable unless the signing user is a collaborator/team member etc.
|
||||
if !isMember {
|
||||
verification.TrustStatus = "untrusted"
|
||||
if verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
// The committing user and the signing user are not the same
|
||||
// This should be marked as questionable unless the signing user is a collaborator/team member etc.
|
||||
verification.TrustStatus = "unmatched"
|
||||
}
|
||||
} else if repoTrustModel == repo_model.CollaboratorCommitterTrustModel && verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
// The committing user and the signing user are not the same and our trustmodel states that they must match
|
||||
verification.TrustStatus = "unmatched"
|
||||
}
|
||||
} else if repoTrustModel == repo_model.CollaboratorCommitterTrustModel && verification.CommittingUser.ID != verification.SigningUser.ID {
|
||||
// The committing user and the signing user are not the same and our trustmodel states that they must match
|
||||
verification.TrustStatus = "unmatched"
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -50,6 +50,7 @@ type PublicKey struct {
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
Verified bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/42wim/sshsig"
|
||||
)
|
||||
|
||||
// ParseCommitWithSSHSignature check if signature is good against keystore.
|
||||
func ParseCommitWithSSHSignature(c *git.Commit, committer *user_model.User) *CommitVerification {
|
||||
// Now try to associate the signature with the committer, if present
|
||||
if committer.ID != 0 {
|
||||
keys, err := ListPublicKeys(committer.ID, db.ListOptions{})
|
||||
if err != nil { // Skipping failed to get ssh keys of user
|
||||
log.Error("ListPublicKeys: %v", err)
|
||||
return &CommitVerification{
|
||||
CommittingUser: committer,
|
||||
Verified: false,
|
||||
Reason: "gpg.error.failed_retrieval_gpg_keys",
|
||||
}
|
||||
}
|
||||
|
||||
committerEmailAddresses, err := user_model.GetEmailAddresses(committer.ID)
|
||||
if err != nil {
|
||||
log.Error("GetEmailAddresses: %v", err)
|
||||
}
|
||||
|
||||
activated := false
|
||||
for _, e := range committerEmailAddresses {
|
||||
if e.IsActivated && strings.EqualFold(e.Email, c.Committer.Email) {
|
||||
activated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
if k.Verified && activated {
|
||||
commitVerification := verifySSHCommitVerification(c.Signature.Signature, c.Signature.Payload, k, committer, committer, c.Committer.Email)
|
||||
if commitVerification != nil {
|
||||
return commitVerification
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &CommitVerification{
|
||||
CommittingUser: committer,
|
||||
Verified: false,
|
||||
Reason: NoKeyFound,
|
||||
}
|
||||
}
|
||||
|
||||
func verifySSHCommitVerification(sig, payload string, k *PublicKey, committer, signer *user_model.User, email string) *CommitVerification {
|
||||
if err := sshsig.Verify(bytes.NewBuffer([]byte(payload)), []byte(sig), []byte(k.Content), "git"); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &CommitVerification{ // Everything is ok
|
||||
CommittingUser: committer,
|
||||
Verified: true,
|
||||
Reason: fmt.Sprintf("%s / %s", signer.Name, k.Fingerprint),
|
||||
SigningUser: signer,
|
||||
SigningSSHKey: k,
|
||||
SigningEmail: email,
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,16 @@
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/42wim/sshsig"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -185,3 +190,309 @@ func Test_calcFingerprint(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// Generated with "ssh-keygen -C test@rekor.dev -f id_rsa"
|
||||
sshPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEA16H5ImoRO7mr41r8Z8JFBdu6jIM+6XU8M0r9F81RuhLYqzr9zw1n
|
||||
LeGCqFxPXNBKm8ZyH2BCsBHsbXbwe85IMHM3SUh8X/9fI0Lpi5/xbqAproFUpNR+UJYv6s
|
||||
8AaWk5zpN1rmpBrqGFJfGQKJCioDiiwNGmSdVkUNmQmYIANxJMDWYmNe8vUOh6nYEHB+lz
|
||||
fGgDAAzVSXTACW994UkSY47AD05swU4rIT/JWA6BkUrEhO//F0QQhFeROCPJiPRhJXGcFf
|
||||
9SicffJqR/ELzM1zNYnRXMD0bbdTUwDrIcIFFNBbtcfJVOUUCGumSlt+qjUC7y8cvwbHAu
|
||||
wf5nS6baA7P6LfTYplF2XIAkdWtkN6O1ouoyIHICXMlddDW2vNaJeEXTeKjx51WSM7qPnQ
|
||||
ZKsBtwjLQeEY/OPkIvu88lNNYSD63qMUA12msohjwVFCIgJVvYLIrkViczZ7t3L7lgy1X0
|
||||
CJI4e1roOfM/r9jTieyDHchEYpZYcw3L1R2qtePlAAAFiHdJQKl3SUCpAAAAB3NzaC1yc2
|
||||
EAAAGBANeh+SJqETu5q+Na/GfCRQXbuoyDPul1PDNK/RfNUboS2Ks6/c8NZy3hgqhcT1zQ
|
||||
SpvGch9gQrAR7G128HvOSDBzN0lIfF//XyNC6Yuf8W6gKa6BVKTUflCWL+rPAGlpOc6Tda
|
||||
5qQa6hhSXxkCiQoqA4osDRpknVZFDZkJmCADcSTA1mJjXvL1Doep2BBwfpc3xoAwAM1Ul0
|
||||
wAlvfeFJEmOOwA9ObMFOKyE/yVgOgZFKxITv/xdEEIRXkTgjyYj0YSVxnBX/UonH3yakfx
|
||||
C8zNczWJ0VzA9G23U1MA6yHCBRTQW7XHyVTlFAhrpkpbfqo1Au8vHL8GxwLsH+Z0um2gOz
|
||||
+i302KZRdlyAJHVrZDejtaLqMiByAlzJXXQ1trzWiXhF03io8edVkjO6j50GSrAbcIy0Hh
|
||||
GPzj5CL7vPJTTWEg+t6jFANdprKIY8FRQiICVb2CyK5FYnM2e7dy+5YMtV9AiSOHta6Dnz
|
||||
P6/Y04nsgx3IRGKWWHMNy9UdqrXj5QAAAAMBAAEAAAGAJyaOcFQnuttUPRxY9ZHNLGofrc
|
||||
Fqm8KgYoO7/iVWMF2Zn0U/rec2E5t9OIpCEozy7uOR9uZoVUV70sgkk6X5b2qL4C9b/aYF
|
||||
JQbSFnq8wCQuTTPIJYE7SfBq1Mwuu/TR/RLC7B74u/cxkJkSXnscO9Dso+ussH0hEJjf6y
|
||||
8yUM1up4Qjbel2gs8i7BPwLdySDkVoPgsWcpbTAyOODGhTAWZ6soy/rD1AEXJeYTGJDtMv
|
||||
aR+WBihig1TO1g2RWt9bqqiG7PIlljd3ZsjSSU5y3t6ZN/8j5keKD032EtxbZB0WFD3Ar4
|
||||
FbFwlW+urb2MQ0JyNKOio3nhdjolXYkJa+C6LXdaaml/8BhMR1eLoMe8nS45w76o8mdJWX
|
||||
wsirB8tvjCLY0QBXgGv/1DTsKu/wEFCW2/Y0e50gF7pHAlYFNmKDcgI9OyORRYhFbV4D82
|
||||
fI8JLQ42ZJkS/0t6xQma8WC88pbHGEuVSB6CE/p25fyYRX+UPTQ79tWFvLV4kNQAaBAAAA
|
||||
wEvyd6H8ePyBXImg8JzGxthufB0eXSfZBrabjf6e6bR2ivpJsHmB64gbMkV6MFV7EWYX1B
|
||||
wYPQxf4gA2Ez7aJvDtfE7uV6pa0WJS3hW1+be8DHEftmLSbTy/TEvDujNb2gqoi7uWQXWJ
|
||||
yYWZlYO65r1a6HucryQ8+78fTuTRbZALO43vNGz0oXH1hPSddkcbNAhZTsD0rQKNwqVTe5
|
||||
wl+6Cduy/CQwjHLYrY73MyWy1Vh1LXhAdGMPnWZwGIu/dnkgAAAMEA9KuaoGnfnLQkrjeR
|
||||
tO4RCRS2quNRvm4L6i4vHgTDsYtoSlR1ujge7SGOOmIPS4XVjZN5zzCOA7+EDVnuz3WWmx
|
||||
hmkjpG1YxzmJGaWoYdeo3a6UgJtisfMp8eUKqjJT1mhsCliCWtaOQNRoQieDQmgwZzSX/v
|
||||
ZiGsOIKa6cR37eKvOJSjVrHsAUzdtYrmi8P2gvAUFWyzXobAtpzHcWrwWkOEIm04G0OGXb
|
||||
J46hfIX3f45E5EKXvFzexGgVOD2I7hAAAAwQDhniYAizfW9YfG7UJWekkl42xMP7Cb8b0W
|
||||
SindSIuE8bFTukV1yxbmNZp/f0pKvn/DWc2n0I0bwSGZpy8BCY46RKKB2DYQavY/tGcC1N
|
||||
AynKuvbtWs11A0mTXmq3WwHVXQDozMwJ2nnHpm0UHspPuHqkYpurlP+xoFsocaQ9QwITyp
|
||||
lL4qHtXBEzaT8okkcGZBHdSx3gk4TzCsEDOP7ZZPLq42lpKMK10zFPTMd0maXtJDYKU/b4
|
||||
gAATvvPoylyYUAAAAOdGVzdEByZWtvci5kZXYBAgMEBQ==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
`
|
||||
sshPublicKey = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDXofkiahE7uavjWvxnwkUF27qMgz7pdTwzSv0XzVG6EtirOv3PDWct4YKoXE9c0EqbxnIfYEKwEextdvB7zkgwczdJSHxf/18jQumLn/FuoCmugVSk1H5Qli/qzwBpaTnOk3WuakGuoYUl8ZAokKKgOKLA0aZJ1WRQ2ZCZggA3EkwNZiY17y9Q6HqdgQcH6XN8aAMADNVJdMAJb33hSRJjjsAPTmzBTishP8lYDoGRSsSE7/8XRBCEV5E4I8mI9GElcZwV/1KJx98mpH8QvMzXM1idFcwPRtt1NTAOshwgUU0Fu1x8lU5RQIa6ZKW36qNQLvLxy/BscC7B/mdLptoDs/ot9NimUXZcgCR1a2Q3o7Wi6jIgcgJcyV10Nba81ol4RdN4qPHnVZIzuo+dBkqwG3CMtB4Rj84+Qi+7zyU01hIPreoxQDXaayiGPBUUIiAlW9gsiuRWJzNnu3cvuWDLVfQIkjh7Wug58z+v2NOJ7IMdyERillhzDcvVHaq14+U= test@rekor.dev
|
||||
`
|
||||
// Generated with "ssh-keygen -C other-test@rekor.dev -f id_rsa"
|
||||
otherSSHPrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEAw/WCSWC9TEvCQOwO+T68EvNa3OSIv1Y0+sT8uSvyjPyEO0+p0t8C
|
||||
g/zy67vOxiQpU5jN6MItjXAjMmeCm8GKMt6gk+cDoaAev/ZfjuzSL7RayExpmhBleh2X3G
|
||||
KLkkXF9ABFNchlTqSLOZiEjDoNpbFv16KT1sE6CqW8DjxXQkQk9JK65hLH+BxeWMNCEJVa
|
||||
Cma4X04aJmC7zJAi5yGeeT0SKVqMohavF90O6XiYFCQHuwXPPyHfocqgudmXnozz+6D6ax
|
||||
JKZMwQsNp3WKumOjlzWnxBCCB1l2jN6Rag8aJ2277iMFXRwjTL/8jaEsW4KkysDf0GjV2/
|
||||
iqbr0q5b0arDYbv7CrGBR+uH0wGz/Zog1x5iZANObhZULpDrLVJidEMc27HXBb7PMsNDy7
|
||||
BGYRB1yc0d0y83p8mUqvOlWSArxn1WnAZO04pAgTrclrhEh4ZXOkn2Sn82eu3DpQ8inkol
|
||||
Y4IfnhIfbOIeemoUNq1tOUquhow9GLRM6INieHLBAAAFkPPnA1jz5wNYAAAAB3NzaC1yc2
|
||||
EAAAGBAMP1gklgvUxLwkDsDvk+vBLzWtzkiL9WNPrE/Lkr8oz8hDtPqdLfAoP88uu7zsYk
|
||||
KVOYzejCLY1wIzJngpvBijLeoJPnA6GgHr/2X47s0i+0WshMaZoQZXodl9xii5JFxfQART
|
||||
XIZU6kizmYhIw6DaWxb9eik9bBOgqlvA48V0JEJPSSuuYSx/gcXljDQhCVWgpmuF9OGiZg
|
||||
u8yQIuchnnk9EilajKIWrxfdDul4mBQkB7sFzz8h36HKoLnZl56M8/ug+msSSmTMELDad1
|
||||
irpjo5c1p8QQggdZdozekWoPGidtu+4jBV0cI0y//I2hLFuCpMrA39Bo1dv4qm69KuW9Gq
|
||||
w2G7+wqxgUfrh9MBs/2aINceYmQDTm4WVC6Q6y1SYnRDHNux1wW+zzLDQ8uwRmEQdcnNHd
|
||||
MvN6fJlKrzpVkgK8Z9VpwGTtOKQIE63Ja4RIeGVzpJ9kp/Nnrtw6UPIp5KJWOCH54SH2zi
|
||||
HnpqFDatbTlKroaMPRi0TOiDYnhywQAAAAMBAAEAAAGAYycx4oEhp55Zz1HijblxnsEmQ8
|
||||
kbbH1pV04fdm7HTxFis0Qu8PVIp5JxNFiWWunnQ1Z5MgI23G9WT+XST4+RpwXBCLWGv9xu
|
||||
UsGOPpqUC/FdUiZf9MXBIxYgRjJS3xORA1KzsnAQ2sclb2I+B1pEl4d9yQWJesvQ25xa2H
|
||||
Utzej/LgWkrk/ogSGRl6ZNImj/421wc0DouGyP+gUgtATt0/jT3LrlmAqUVCXVqssLYH2O
|
||||
r9JTuGUibBJEW2W/c0lsM0jaHa5bGAdL3nhDuF1Q6KFB87mZoNw8c2znYoTzQ3FyWtIEZI
|
||||
V/9oWrkS7V6242SKSR9tJoEzK0jtrKC/FZwBiI4hPcwoqY6fZbT1701i/n50xWEfEUOLVm
|
||||
d6VqNKyAbIaZIPN0qfZuD+xdrHuM3V6k/rgFxGl4XTrp/N4AsruiQs0nRQKNTw3fHE0zPq
|
||||
UTxSeMvjywRCepxhBFCNh8NHydapclHtEPEGdTVHohL3krJehstPO/IuRyKLfSVtL1AAAA
|
||||
wQCmGA8k+uW6mway9J3jp8mlMhhp3DCX6DAcvalbA/S5OcqMyiTM3c/HD5OJ6OYFDldcqu
|
||||
MPEgLRL2HfxL29LsbQSzjyOIrfp5PLJlo70P5lXS8u2QPbo4/KQJmQmsIX18LDyU2zRtNA
|
||||
C2WfBiHSZV+guLhmHms9S5gQYKt2T5OnY/W0tmnInx9lmFCMC+XKS1iSQ2o433IrtCPQJp
|
||||
IXZd59OQpO9QjJABgJIDtXxFIXt45qpXduDPJuggrhg81stOwAAADBAPX73u/CY+QUPts+
|
||||
LV185Z4mZ2y+qu2ZMCAU3BnpHktGZZ1vFN1Xq9o8KdnuPZ+QJRdO8eKMWpySqrIdIbTYLm
|
||||
9nXmVH0uNECIEAvdU+wgKeR+BSHxCRVuTF4YSygmNadgH/z+oRWLgOblGo2ywFBoXsIAKQ
|
||||
paNu1MFGRUmhz67+dcpkkBUDRU9loAgBKexMo8D9vkR0YiHLOUjCrtmEZRNm0YRZt0gQhD
|
||||
ZSD1fOH0fZDcCVNpGP2zqAKos4EGLnkwAAAMEAy/AuLtPKA2u9oCA8e18ZnuQRAi27FBVU
|
||||
rU2D7bMg1eS0IakG8v0gE9K6WdYzyArY1RoKB3ZklK5VmJ1cOcWc2x3Ejc5jcJgc8cC6lZ
|
||||
wwjpE8HfWL1kIIYgPdcexqFc+l6MdgH6QMKU3nLg1LsM4v5FEldtk/2dmnw620xnFfstpF
|
||||
VxSZNdKrYfM/v9o6sRaDRqSfH1dG8BvkUxPznTAF+JDxBENcKXYECcq9f6dcl1w5IEnNTD
|
||||
Wry/EKQvgvOUjbAAAAFG90aGVyLXRlc3RAcmVrb3IuZGV2AQIDBAUG
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
`
|
||||
otherSSHPublicKey = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDD9YJJYL1MS8JA7A75PrwS81rc5Ii/VjT6xPy5K/KM/IQ7T6nS3wKD/PLru87GJClTmM3owi2NcCMyZ4KbwYoy3qCT5wOhoB6/9l+O7NIvtFrITGmaEGV6HZfcYouSRcX0AEU1yGVOpIs5mISMOg2lsW/XopPWwToKpbwOPFdCRCT0krrmEsf4HF5Yw0IQlVoKZrhfThomYLvMkCLnIZ55PRIpWoyiFq8X3Q7peJgUJAe7Bc8/Id+hyqC52ZeejPP7oPprEkpkzBCw2ndYq6Y6OXNafEEIIHWXaM3pFqDxonbbvuIwVdHCNMv/yNoSxbgqTKwN/QaNXb+KpuvSrlvRqsNhu/sKsYFH64fTAbP9miDXHmJkA05uFlQukOstUmJ0QxzbsdcFvs8yw0PLsEZhEHXJzR3TLzenyZSq86VZICvGfVacBk7TikCBOtyWuESHhlc6SfZKfzZ67cOlDyKeSiVjgh+eEh9s4h56ahQ2rW05Sq6GjD0YtEzog2J4csE= other-test@rekor.dev
|
||||
`
|
||||
|
||||
// Generated with ssh-keygen -C test@rekor.dev -t ed25519 -f id_ed25519
|
||||
ed25519PrivateKey = `-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBB45zRHxPPFtabwS3Vd6Lb9vMe+tIHZj2qN5VQ+bgLfQAAAJgyRa3cMkWt
|
||||
3AAAAAtzc2gtZWQyNTUxOQAAACBB45zRHxPPFtabwS3Vd6Lb9vMe+tIHZj2qN5VQ+bgLfQ
|
||||
AAAED7y4N/DsVnRQiBZNxEWdsJ9RmbranvtQ3X9jnb6gFed0HjnNEfE88W1pvBLdV3otv2
|
||||
8x760gdmPao3lVD5uAt9AAAADnRlc3RAcmVrb3IuZGV2AQIDBAUGBw==
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
`
|
||||
ed25519PublicKey = `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEHjnNEfE88W1pvBLdV3otv28x760gdmPao3lVD5uAt9 test@rekor.dev
|
||||
`
|
||||
)
|
||||
|
||||
func TestFromOpenSSH(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
pub string
|
||||
priv string
|
||||
}{
|
||||
{
|
||||
name: "rsa",
|
||||
pub: sshPublicKey,
|
||||
priv: sshPrivateKey,
|
||||
},
|
||||
{
|
||||
name: "ed25519",
|
||||
pub: ed25519PublicKey,
|
||||
priv: ed25519PrivateKey,
|
||||
},
|
||||
} {
|
||||
if _, err := exec.LookPath("ssh-keygen"); err != nil {
|
||||
t.Skip("skip TestFromOpenSSH: missing ssh-keygen in PATH")
|
||||
}
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt := tt
|
||||
|
||||
// Test that a signature from the cli can validate here.
|
||||
td := t.TempDir()
|
||||
|
||||
data := []byte("hello, ssh world")
|
||||
dataPath := write(t, []byte(data), td, "data")
|
||||
|
||||
privPath := write(t, []byte(tt.priv), td, "id")
|
||||
write(t, []byte(tt.pub), td, "id.pub")
|
||||
|
||||
sigPath := dataPath + ".sig"
|
||||
run(t, nil, "ssh-keygen", "-Y", "sign", "-n", "file", "-f", privPath, dataPath)
|
||||
|
||||
sigBytes, err := ioutil.ReadFile(sigPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := sshsig.Verify(bytes.NewReader(data), sigBytes, []byte(tt.pub), "file"); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// It should not verify if we check against another public key
|
||||
if err := sshsig.Verify(bytes.NewReader(data), sigBytes, []byte(otherSSHPublicKey), "file"); err == nil {
|
||||
t.Error("expected error with incorrect key")
|
||||
}
|
||||
|
||||
// It should not verify if the data is tampered
|
||||
if err := sshsig.Verify(strings.NewReader("bad data"), sigBytes, []byte(sshPublicKey), "file"); err == nil {
|
||||
t.Error("expected error with incorrect data")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestToOpenSSH(t *testing.T) {
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
pub string
|
||||
priv string
|
||||
}{
|
||||
{
|
||||
name: "rsa",
|
||||
pub: sshPublicKey,
|
||||
priv: sshPrivateKey,
|
||||
},
|
||||
{
|
||||
name: "ed25519",
|
||||
pub: ed25519PublicKey,
|
||||
priv: ed25519PrivateKey,
|
||||
},
|
||||
} {
|
||||
if _, err := exec.LookPath("ssh-keygen"); err != nil {
|
||||
t.Skip("skip TestToOpenSSH: missing ssh-keygen in PATH")
|
||||
}
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt := tt
|
||||
// Test that a signature from here can validate in the CLI.
|
||||
td := t.TempDir()
|
||||
|
||||
data := []byte("hello, ssh world")
|
||||
write(t, []byte(data), td, "data")
|
||||
|
||||
armored, err := sshsig.Sign([]byte(tt.priv), bytes.NewReader(data), "file")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sigPath := write(t, []byte(armored), td, "oursig")
|
||||
|
||||
// Create an allowed_signers file with two keys to check against.
|
||||
allowedSigner := "test@rekor.dev " + tt.pub + "\n"
|
||||
allowedSigner += "othertest@rekor.dev " + otherSSHPublicKey + "\n"
|
||||
allowedSigners := write(t, []byte(allowedSigner), td, "allowed_signer")
|
||||
|
||||
// We use the correct principal here so it should work.
|
||||
run(t, data, "ssh-keygen", "-Y", "verify", "-f", allowedSigners,
|
||||
"-I", "test@rekor.dev", "-n", "file", "-s", sigPath)
|
||||
|
||||
// Just to be sure, check against the other public key as well.
|
||||
runErr(t, data, "ssh-keygen", "-Y", "verify", "-f", allowedSigners,
|
||||
"-I", "othertest@rekor.dev", "-n", "file", "-s", sigPath)
|
||||
|
||||
// It should error if we run it against other data
|
||||
data = []byte("other data!")
|
||||
runErr(t, data, "ssh-keygen", "-Y", "check-novalidate", "-n", "file", "-s", sigPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
data := []byte("my good data to be signed!")
|
||||
|
||||
// Create one extra signature for all the tests.
|
||||
otherSig, err := sshsig.Sign([]byte(otherSSHPrivateKey), bytes.NewReader(data), "file")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
pub string
|
||||
priv string
|
||||
}{
|
||||
{
|
||||
name: "rsa",
|
||||
pub: sshPublicKey,
|
||||
priv: sshPrivateKey,
|
||||
},
|
||||
{
|
||||
name: "ed25519",
|
||||
pub: ed25519PublicKey,
|
||||
priv: ed25519PrivateKey,
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tt := tt
|
||||
sig, err := sshsig.Sign([]byte(tt.priv), bytes.NewReader(data), "file")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Check the signature against that data and public key
|
||||
if err := sshsig.Verify(bytes.NewReader(data), sig, []byte(tt.pub), "file"); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Now check it against invalid data.
|
||||
if err := sshsig.Verify(strings.NewReader("invalid data!"), sig, []byte(tt.pub), "file"); err == nil {
|
||||
t.Error("expected error!")
|
||||
}
|
||||
|
||||
// Now check it against the wrong key.
|
||||
if err := sshsig.Verify(bytes.NewReader(data), sig, []byte(otherSSHPublicKey), "file"); err == nil {
|
||||
t.Error("expected error!")
|
||||
}
|
||||
|
||||
// Now check it against an invalid signature data.
|
||||
if err := sshsig.Verify(bytes.NewReader(data), []byte("invalid signature!"), []byte(tt.pub), "file"); err == nil {
|
||||
t.Error("expected error!")
|
||||
}
|
||||
|
||||
// Once more, use the wrong signature and check it against the original (wrong public key)
|
||||
if err := sshsig.Verify(bytes.NewReader(data), otherSig, []byte(tt.pub), "file"); err == nil {
|
||||
t.Error("expected error!")
|
||||
}
|
||||
// It should work against the correct public key.
|
||||
if err := sshsig.Verify(bytes.NewReader(data), otherSig, []byte(otherSSHPublicKey), "file"); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func write(t *testing.T, d []byte, fp ...string) string {
|
||||
p := filepath.Join(fp...)
|
||||
if err := ioutil.WriteFile(p, d, 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func run(t *testing.T, stdin []byte, args ...string) {
|
||||
t.Helper()
|
||||
/* #nosec */
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.Stdin = bytes.NewReader(stdin)
|
||||
out, err := cmd.CombinedOutput()
|
||||
t.Logf("cmd %v: %s", cmd, string(out))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runErr(t *testing.T, stdin []byte, args ...string) {
|
||||
t.Helper()
|
||||
/* #nosec */
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.Stdin = bytes.NewReader(stdin)
|
||||
out, err := cmd.CombinedOutput()
|
||||
t.Logf("cmd %v: %s", cmd, string(out))
|
||||
if err == nil {
|
||||
t.Fatal("expected error")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package asymkey
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"github.com/42wim/sshsig"
|
||||
)
|
||||
|
||||
// VerifySSHKey marks a SSH key as verified
|
||||
func VerifySSHKey(ownerID int64, fingerprint, token, signature string) (string, error) {
|
||||
ctx, committer, err := db.TxContext()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
key := new(PublicKey)
|
||||
|
||||
has, err := db.GetEngine(ctx).Where("owner_id = ? AND fingerprint = ?", ownerID, fingerprint).Get(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
} else if !has {
|
||||
return "", ErrKeyNotExist{}
|
||||
}
|
||||
|
||||
if err := sshsig.Verify(bytes.NewBuffer([]byte(token)), []byte(signature), []byte(key.Content), "gitea"); err != nil {
|
||||
log.Error("Unable to validate token signature. Error: %v", err)
|
||||
return "", ErrSSHInvalidTokenSignature{
|
||||
Fingerprint: key.Fingerprint,
|
||||
}
|
||||
}
|
||||
|
||||
key.Verified = true
|
||||
if _, err := db.GetEngine(ctx).ID(key.ID).Cols("verified").Update(key); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err := committer.Commit(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return key.Fingerprint, nil
|
||||
}
|
||||
@@ -361,6 +361,8 @@ var migrations = []Migration{
|
||||
NewMigration("Create key/value table for user settings", createUserSettingsTable),
|
||||
// v203 -> v204
|
||||
NewMigration("Add Sorting to ProjectIssue table", addProjectIssueSorting),
|
||||
// v204 -> v205
|
||||
NewMigration("Add key is verified to ssh key", addSSHKeyIsVerified),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current db version
|
||||
|
||||
@@ -21,5 +21,4 @@ func createUserSettingsTable(x *xorm.Engine) error {
|
||||
return fmt.Errorf("sync2: %v", err)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package migrations
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
func addSSHKeyIsVerified(x *xorm.Engine) error {
|
||||
type PublicKey struct {
|
||||
Verified bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
return x.Sync(new(PublicKey))
|
||||
}
|
||||
@@ -629,7 +629,18 @@ gpg_token_help = You can generate a signature using:
|
||||
gpg_token_code = echo "%s" | gpg -a --default-key %s --detach-sig
|
||||
gpg_token_signature = Armored GPG signature
|
||||
key_signature_gpg_placeholder = Begins with '-----BEGIN PGP SIGNATURE-----'
|
||||
verify_gpg_key_success = The GPG key '%s' has been verified.
|
||||
verify_gpg_key_success = GPG key '%s' has been verified.
|
||||
ssh_key_verified=Verified Key
|
||||
ssh_key_verified_long=Key has been verified with a token and can be used to verify commits matching any activated email addresses for this user.
|
||||
ssh_key_verify=Verify
|
||||
ssh_invalid_token_signature = The provided SSH key, signature or token do not match or token is out-of-date.
|
||||
ssh_token_required = You must provide a signature for the below token
|
||||
ssh_token = Token
|
||||
ssh_token_help = You can generate a signature using:
|
||||
ssh_token_code = echo -n "%s" | ssh-keygen -Y sign -n gitea -f /path_to_your_pubkey
|
||||
ssh_token_signature = Armored SSH signature
|
||||
key_signature_ssh_placeholder = Begins with '-----BEGIN SSH SIGNATURE-----'
|
||||
verify_ssh_key_success = SSH key '%s' has been verified.
|
||||
subkeys = Subkeys
|
||||
key_id = Key ID
|
||||
key_name = Key Name
|
||||
@@ -1084,6 +1095,7 @@ commits.signed_by = Signed by
|
||||
commits.signed_by_untrusted_user = Signed by untrusted user
|
||||
commits.signed_by_untrusted_user_unmatched = Signed by untrusted user who does not match committer
|
||||
commits.gpg_key_id = GPG Key ID
|
||||
commits.ssh_key_fingerprint = SSH Key Fingerprint
|
||||
|
||||
ext_issues = Ext. Issues
|
||||
ext_issues.desc = Link to an external issue tracker.
|
||||
|
||||
@@ -184,6 +184,28 @@ func KeysPost(ctx *context.Context) {
|
||||
}
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
case "verify_ssh":
|
||||
token := asymkey_model.VerificationToken(ctx.User, 1)
|
||||
lastToken := asymkey_model.VerificationToken(ctx.User, 0)
|
||||
|
||||
fingerprint, err := asymkey_model.VerifySSHKey(ctx.User.ID, form.Fingerprint, token, form.Signature)
|
||||
if err != nil && asymkey_model.IsErrSSHInvalidTokenSignature(err) {
|
||||
fingerprint, err = asymkey_model.VerifySSHKey(ctx.User.ID, form.Fingerprint, lastToken, form.Signature)
|
||||
}
|
||||
if err != nil {
|
||||
ctx.Data["HasSSHVerifyError"] = true
|
||||
switch {
|
||||
case asymkey_model.IsErrSSHInvalidTokenSignature(err):
|
||||
loadKeysData(ctx)
|
||||
ctx.Data["Err_Signature"] = true
|
||||
ctx.Data["Fingerprint"] = err.(asymkey_model.ErrSSHInvalidTokenSignature).Fingerprint
|
||||
ctx.RenderWithErr(ctx.Tr("settings.ssh_invalid_token_signature"), tplSettingsKeys, &form)
|
||||
default:
|
||||
ctx.ServerError("VerifySSH", err)
|
||||
}
|
||||
}
|
||||
ctx.Flash.Success(ctx.Tr("settings.verify_ssh_key_success", fingerprint))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
|
||||
|
||||
default:
|
||||
ctx.Flash.Warning("Function not implemented")
|
||||
@@ -268,4 +290,5 @@ func loadKeysData(ctx *context.Context) {
|
||||
ctx.Data["Principals"] = principals
|
||||
|
||||
ctx.Data["VerifyingID"] = ctx.FormString("verify_gpg")
|
||||
ctx.Data["VerifyingFingerprint"] = ctx.FormString("verify_ssh")
|
||||
}
|
||||
@@ -349,12 +349,13 @@ func (f *AddOpenIDForm) Validate(req *http.Request, errs binding.Errors) binding
|
||||
|
||||
// AddKeyForm form for adding SSH/GPG key
|
||||
type AddKeyForm struct {
|
||||
Type string `binding:"OmitEmpty"`
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
Content string `binding:"Required"`
|
||||
Signature string `binding:"OmitEmpty"`
|
||||
KeyID string `binding:"OmitEmpty"`
|
||||
IsWritable bool
|
||||
Type string `binding:"OmitEmpty"`
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
Content string `binding:"Required"`
|
||||
Signature string `binding:"OmitEmpty"`
|
||||
KeyID string `binding:"OmitEmpty"`
|
||||
Fingerprint string `binding:"OmitEmpty"`
|
||||
IsWritable bool
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
||||
@@ -109,17 +109,32 @@
|
||||
{{if .Verification.Verified}}
|
||||
{{if ne .Verification.SigningUser.ID 0}}
|
||||
{{svg "octicon-shield-check" 16 "mr-3"}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{if .Verification.SigningSSHKey}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
|
||||
{{.Verification.SigningSSHKey.Fingerprint}}
|
||||
{{else}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{svg "octicon-shield-lock" 16 "mr-3"}}
|
||||
<span class="ui text mr-3 tooltip" data-content="{{.i18n.Tr "gpg.default_key"}}">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{if .Verification.SigningSSHKey}}
|
||||
<span class="ui text mr-3 tooltip" data-content="{{.i18n.Tr "gpg.default_key"}}">{{.i18n.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
|
||||
{{.Verification.SigningSSHKey.Fingerprint}}
|
||||
{{else}}
|
||||
<span class="ui text mr-3 tooltip" data-content="{{.i18n.Tr "gpg.default_key"}}">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{else if .Verification.Warning}}
|
||||
{{svg "octicon-shield" 16 "mr-3"}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{if .Verification.SigningSSHKey}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
|
||||
{{.Verification.SigningSSHKey.Fingerprint}}
|
||||
{{else}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.gpg_key_id"}}:</span>
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{end}}
|
||||
{{else}}
|
||||
{{if .Verification.SigningKey}}
|
||||
{{if ne .Verification.SigningKey.KeyID ""}}
|
||||
@@ -128,6 +143,13 @@
|
||||
{{.Verification.SigningKey.KeyID}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .Verification.SigningSSHKey}}
|
||||
{{if ne .Verification.SigningSSHKey.Fingerprint ""}}
|
||||
{{svg "octicon-shield" 16 "mr-3"}}
|
||||
<span class="ui text mr-3">{{.i18n.Tr "repo.commits.ssh_key_fingerprint"}}:</span>
|
||||
{{.Verification.SigningSSHKey.Fingerprint}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -41,11 +41,18 @@
|
||||
<button class="ui red tiny button delete-button{{if index $.ExternalKeys $index}} disabled{{end}}" data-modal-id="delete-ssh" data-url="{{$.Link}}/delete?type=ssh" data-id="{{.ID}}"{{if index $.ExternalKeys $index}} title="{{$.i18n.Tr "settings.ssh_externally_managed"}}"{{end}}>
|
||||
{{$.i18n.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
{{if and (not .Verified) (ne $.VerifyingFingerprint .Fingerprint)}}
|
||||
<a class="ui blue tiny show-panel button" href="{{$.Link}}?verify_ssh={{.Fingerprint}}">{{$.i18n.Tr "settings.ssh_key_verify"}}</a>
|
||||
{{end}}
|
||||
|
||||
</div>
|
||||
<div class="left floated content">
|
||||
<span class="{{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.i18n.Tr "settings.key_state_desc"}}" data-variation="inverted tiny"{{end}}>{{svg "octicon-key" 32}}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
{{if .Verified}}
|
||||
<span class="tooltip" data-content="{{$.i18n.Tr "settings.ssh_key_verified_long"}}">{{svg "octicon-shield-check"}} <strong>{{$.i18n.Tr "settings.ssh_key_verified"}}</strong></span>
|
||||
{{end}}
|
||||
<strong>{{.Name}}</strong>
|
||||
<div class="print meta">
|
||||
{{.Fingerprint}}
|
||||
@@ -55,6 +62,37 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{if and (not .Verified) (eq $.VerifyingFingerprint .Fingerprint)}}
|
||||
<div class="ui segment">
|
||||
<h4>{{$.i18n.Tr "settings.ssh_token_required"}}</h4>
|
||||
<form class="ui form{{if $.HasSSHVerifyError}} error{{end}}" action="{{$.Link}}" method="post">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<input type="hidden" name="title" value="none">
|
||||
<input type="hidden" name="content" value="{{.Content}}">
|
||||
<input type="hidden" name="fingerprint" value="{{.Fingerprint}}">
|
||||
<div class="field">
|
||||
<label for="token">{{$.i18n.Tr "settings.ssh_token"}}</label>
|
||||
<input readonly="" value="{{$.TokenToSign}}">
|
||||
<div class="help">
|
||||
<p>{{$.i18n.Tr "settings.ssh_token_help"}}</p>
|
||||
<p><code>{{$.i18n.Tr "settings.ssh_token_code" $.TokenToSign}}</code></p>
|
||||
</div>
|
||||
<br>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="signature">{{$.i18n.Tr "settings.ssh_token_signature"}}</label>
|
||||
<textarea id="ssh-key-signature" name="signature" placeholder="{{$.i18n.Tr "settings.key_signature_ssh_placeholder"}}" required>{{$.signature}}</textarea>
|
||||
</div>
|
||||
<input name="type" type="hidden" value="verify_ssh">
|
||||
<button class="ui green button">
|
||||
{{$.i18n.Tr "settings.ssh_key_verify"}}
|
||||
</button>
|
||||
<a class="ui red button" href="{{$.Link}}">
|
||||
{{$.i18n.Tr "settings.cancel"}}
|
||||
</a>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
# Armored ssh signatures in go
|
||||
|
||||
[](https://pkg.go.dev/github.com/42wim/sshsig#section-documentation)
|
||||
|
||||
Package sshsig implements signing/verifying armored SSH signatures.
|
||||
You can use this package to sign data and verify signatures using your ssh private keys or your ssh agent.
|
||||
It gives the same output as using `ssh-keygen`, eg when signing `ssh-keygen -Y sign -f keyfile -n namespace data`
|
||||
|
||||
This code is based upon work by <https://github.com/sigstore/rekor>
|
||||
|
||||
References: <https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig>
|
||||
|
||||
You can find some examples on how to use this library on: <https://pkg.go.dev/github.com/42wim/sshsig#pkg-examples>
|
||||
|
||||
## Examples
|
||||
|
||||
```golang
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/42wim/sshsig"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func ExampleSignWithAgent() {
|
||||
// This example will panic when you don't have a ssh-agent running.
|
||||
conn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ag := agent.NewClient(conn)
|
||||
|
||||
// This public key must match in your agent (use `ssh-add -L` to get the public key)
|
||||
pubkey := []byte(`ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAo3D7CGN01tTYY/dLKXEv8RxRyxa32c51X0uKMhnMab wim@localhost`)
|
||||
//
|
||||
data := []byte("hello world")
|
||||
|
||||
res, err := sshsig.SignWithAgent(pubkey, ag, bytes.NewBuffer(data), "file")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(res))
|
||||
}
|
||||
|
||||
func ExampleSign() {
|
||||
privkey := []byte(`-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACCOjP6i4Pm/pYAAmpAMNZ6xrbHl9RW8xdul6kzIWuKMMAAAAIhoQm34aEJt
|
||||
+AAAAAtzc2gtZWQyNTUxOQAAACCOjP6i4Pm/pYAAmpAMNZ6xrbHl9RW8xdul6kzIWuKMMA
|
||||
AAAEBfIl93TLj6qHeg37GnPuZ00h8OVv1mzlhy0rhuO4Y0do6M/qLg+b+lgACakAw1nrGt
|
||||
seX1FbzF26XqTMha4owwAAAAAAECAwQF
|
||||
-----END OPENSSH PRIVATE KEY-----`)
|
||||
|
||||
data := []byte("hello world")
|
||||
|
||||
res, err := sshsig.Sign(privkey, bytes.NewBuffer(data), "file")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(string(res))
|
||||
|
||||
// Output:
|
||||
// -----BEGIN SSH SIGNATURE-----
|
||||
// U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgjoz+ouD5v6WAAJqQDDWesa2x5f
|
||||
// UVvMXbpepMyFrijDAAAAAEZmlsZQAAAAAAAAAGc2hhNTEyAAAAUwAAAAtzc2gtZWQyNTUx
|
||||
// OQAAAEBeu9Z+vLxBORysiqEbTzJP0EZKG0/aE5HpTtvimjQS6mHZCAGFg+kimNatBE0Y1j
|
||||
// gS4pfD73TlML1SyB5lb/YO
|
||||
// -----END SSH SIGNATURE-----
|
||||
}
|
||||
|
||||
func main() {
|
||||
ExampleSign()
|
||||
}
|
||||
```
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Package sshsig implements signing/verifying armored SSH signatures.
|
||||
You can use this package to sign data and verify signatures using your ssh private keys or your ssh agent.
|
||||
It gives the same output as using `ssh-keygen`, eg when signing `ssh-keygen -Y sign -f keyfile -n namespace data`
|
||||
|
||||
This code is based upon work by https://github.com/sigstore/rekor
|
||||
|
||||
References:
|
||||
- https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig
|
||||
*/
|
||||
package sshsig
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
// Modified by 42wim
|
||||
//
|
||||
// Copyright 2021 The Sigstore Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sshsig
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/42wim/sshsig/pem"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
const (
|
||||
pemType = "SSH SIGNATURE"
|
||||
)
|
||||
|
||||
// Armored returns the signature in an armored format.
|
||||
func Armor(s *ssh.Signature, p ssh.PublicKey, ns string) []byte {
|
||||
sig := WrappedSig{
|
||||
Version: 1,
|
||||
PublicKey: string(p.Marshal()),
|
||||
Namespace: ns,
|
||||
HashAlgorithm: defaultHashAlgorithm,
|
||||
Signature: string(ssh.Marshal(s)),
|
||||
}
|
||||
|
||||
copy(sig.MagicHeader[:], magicHeader)
|
||||
|
||||
enc := pem.EncodeToMemory(&pem.Block{
|
||||
Type: pemType,
|
||||
Bytes: ssh.Marshal(sig),
|
||||
})
|
||||
return enc
|
||||
}
|
||||
|
||||
// Decode parses an armored signature.
|
||||
func Decode(b []byte) (*Signature, error) {
|
||||
pemBlock, _ := pem.Decode(b)
|
||||
if pemBlock == nil {
|
||||
return nil, errors.New("unable to decode pem file")
|
||||
}
|
||||
|
||||
if pemBlock.Type != pemType {
|
||||
return nil, fmt.Errorf("wrong pem block type: %s. Expected SSH-SIGNATURE", pemBlock.Type)
|
||||
}
|
||||
|
||||
// Now we unmarshal it into the Signature block
|
||||
sig := WrappedSig{}
|
||||
if err := ssh.Unmarshal(pemBlock.Bytes, &sig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sig.Version != 1 {
|
||||
return nil, fmt.Errorf("unsupported signature version: %d", sig.Version)
|
||||
}
|
||||
if string(sig.MagicHeader[:]) != magicHeader {
|
||||
return nil, fmt.Errorf("invalid magic header: %s", sig.MagicHeader[:])
|
||||
}
|
||||
if _, ok := supportedHashAlgorithms[sig.HashAlgorithm]; !ok {
|
||||
return nil, fmt.Errorf("unsupported hash algorithm: %s", sig.HashAlgorithm)
|
||||
}
|
||||
|
||||
// Now we can unpack the Signature and PublicKey blocks
|
||||
sshSig := ssh.Signature{}
|
||||
if err := ssh.Unmarshal([]byte(sig.Signature), &sshSig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: check the format here (should be rsa-sha512)
|
||||
|
||||
pk, err := ssh.ParsePublicKey([]byte(sig.PublicKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Signature{
|
||||
signature: &sshSig,
|
||||
pk: pk,
|
||||
hashAlg: sig.HashAlgorithm,
|
||||
}, nil
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
module github.com/42wim/sshsig
|
||||
|
||||
go 1.17
|
||||
|
||||
require golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871
|
||||
|
||||
require golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 // indirect
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI=
|
||||
golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1 h1:kwrAHlwJ0DUBZwQ238v+Uod/3eZ8B2K5rYsUHBQvzmI=
|
||||
golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
// Modified by 42wim
|
||||
//
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package pem implements the PEM data encoding, which originated in Privacy
|
||||
// Enhanced Mail. The most common use of PEM encoding today is in TLS keys and
|
||||
// certificates. See RFC 1421.
|
||||
package pem
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A Block represents a PEM encoded structure.
|
||||
//
|
||||
// The encoded form is:
|
||||
// -----BEGIN Type-----
|
||||
// Headers
|
||||
// base64-encoded Bytes
|
||||
// -----END Type-----
|
||||
// where Headers is a possibly empty sequence of Key: Value lines.
|
||||
type Block struct {
|
||||
Type string // The type, taken from the preamble (i.e. "RSA PRIVATE KEY").
|
||||
Headers map[string]string // Optional headers.
|
||||
Bytes []byte // The decoded bytes of the contents. Typically a DER encoded ASN.1 structure.
|
||||
}
|
||||
|
||||
// getLine results the first \r\n or \n delineated line from the given byte
|
||||
// array. The line does not include trailing whitespace or the trailing new
|
||||
// line bytes. The remainder of the byte array (also not including the new line
|
||||
// bytes) is also returned and this will always be smaller than the original
|
||||
// argument.
|
||||
func getLine(data []byte) (line, rest []byte) {
|
||||
i := bytes.IndexByte(data, '\n')
|
||||
var j int
|
||||
if i < 0 {
|
||||
i = len(data)
|
||||
j = i
|
||||
} else {
|
||||
j = i + 1
|
||||
if i > 0 && data[i-1] == '\r' {
|
||||
i--
|
||||
}
|
||||
}
|
||||
return bytes.TrimRight(data[0:i], " \t"), data[j:]
|
||||
}
|
||||
|
||||
// removeSpacesAndTabs returns a copy of its input with all spaces and tabs
|
||||
// removed, if there were any. Otherwise, the input is returned unchanged.
|
||||
//
|
||||
// The base64 decoder already skips newline characters, so we don't need to
|
||||
// filter them out here.
|
||||
func removeSpacesAndTabs(data []byte) []byte {
|
||||
if !bytes.ContainsAny(data, " \t") {
|
||||
// Fast path; most base64 data within PEM contains newlines, but
|
||||
// no spaces nor tabs. Skip the extra alloc and work.
|
||||
return data
|
||||
}
|
||||
result := make([]byte, len(data))
|
||||
n := 0
|
||||
|
||||
for _, b := range data {
|
||||
if b == ' ' || b == '\t' {
|
||||
continue
|
||||
}
|
||||
result[n] = b
|
||||
n++
|
||||
}
|
||||
|
||||
return result[0:n]
|
||||
}
|
||||
|
||||
var (
|
||||
pemStart = []byte("\n-----BEGIN ")
|
||||
pemEnd = []byte("\n-----END ")
|
||||
pemEndOfLine = []byte("-----")
|
||||
)
|
||||
|
||||
// Decode will find the next PEM formatted block (certificate, private key
|
||||
// etc) in the input. It returns that block and the remainder of the input. If
|
||||
// no PEM data is found, p is nil and the whole of the input is returned in
|
||||
// rest.
|
||||
func Decode(data []byte) (p *Block, rest []byte) {
|
||||
// pemStart begins with a newline. However, at the very beginning of
|
||||
// the byte array, we'll accept the start string without it.
|
||||
rest = data
|
||||
if bytes.HasPrefix(data, pemStart[1:]) {
|
||||
rest = rest[len(pemStart)-1 : len(data)]
|
||||
} else if i := bytes.Index(data, pemStart); i >= 0 {
|
||||
rest = rest[i+len(pemStart) : len(data)]
|
||||
} else {
|
||||
return nil, data
|
||||
}
|
||||
|
||||
typeLine, rest := getLine(rest)
|
||||
if !bytes.HasSuffix(typeLine, pemEndOfLine) {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
typeLine = typeLine[0 : len(typeLine)-len(pemEndOfLine)]
|
||||
|
||||
p = &Block{
|
||||
Headers: make(map[string]string),
|
||||
Type: string(typeLine),
|
||||
}
|
||||
|
||||
for {
|
||||
// This loop terminates because getLine's second result is
|
||||
// always smaller than its argument.
|
||||
if len(rest) == 0 {
|
||||
return nil, data
|
||||
}
|
||||
line, next := getLine(rest)
|
||||
|
||||
i := bytes.IndexByte(line, ':')
|
||||
if i == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
// TODO(agl): need to cope with values that spread across lines.
|
||||
key, val := line[:i], line[i+1:]
|
||||
key = bytes.TrimSpace(key)
|
||||
val = bytes.TrimSpace(val)
|
||||
p.Headers[string(key)] = string(val)
|
||||
rest = next
|
||||
}
|
||||
|
||||
var endIndex, endTrailerIndex int
|
||||
|
||||
// If there were no headers, the END line might occur
|
||||
// immediately, without a leading newline.
|
||||
if len(p.Headers) == 0 && bytes.HasPrefix(rest, pemEnd[1:]) {
|
||||
endIndex = 0
|
||||
endTrailerIndex = len(pemEnd) - 1
|
||||
} else {
|
||||
endIndex = bytes.Index(rest, pemEnd)
|
||||
endTrailerIndex = endIndex + len(pemEnd)
|
||||
}
|
||||
|
||||
if endIndex < 0 {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
|
||||
// After the "-----" of the ending line, there should be the same type
|
||||
// and then a final five dashes.
|
||||
endTrailer := rest[endTrailerIndex:]
|
||||
endTrailerLen := len(typeLine) + len(pemEndOfLine)
|
||||
if len(endTrailer) < endTrailerLen {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
|
||||
restOfEndLine := endTrailer[endTrailerLen:]
|
||||
endTrailer = endTrailer[:endTrailerLen]
|
||||
if !bytes.HasPrefix(endTrailer, typeLine) ||
|
||||
!bytes.HasSuffix(endTrailer, pemEndOfLine) {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
|
||||
// The line must end with only whitespace.
|
||||
if s, _ := getLine(restOfEndLine); len(s) != 0 {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
|
||||
base64Data := removeSpacesAndTabs(rest[:endIndex])
|
||||
p.Bytes = make([]byte, base64.StdEncoding.DecodedLen(len(base64Data)))
|
||||
n, err := base64.StdEncoding.Decode(p.Bytes, base64Data)
|
||||
if err != nil {
|
||||
return decodeError(data, rest)
|
||||
}
|
||||
p.Bytes = p.Bytes[:n]
|
||||
|
||||
// the -1 is because we might have only matched pemEnd without the
|
||||
// leading newline if the PEM block was empty.
|
||||
_, rest = getLine(rest[endIndex+len(pemEnd)-1:])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func decodeError(data, rest []byte) (*Block, []byte) {
|
||||
// If we get here then we have rejected a likely looking, but
|
||||
// ultimately invalid PEM block. We need to start over from a new
|
||||
// position. We have consumed the preamble line and will have consumed
|
||||
// any lines which could be header lines. However, a valid preamble
|
||||
// line is not a valid header line, therefore we cannot have consumed
|
||||
// the preamble line for the any subsequent block. Thus, we will always
|
||||
// find any valid block, no matter what bytes precede it.
|
||||
//
|
||||
// For example, if the input is
|
||||
//
|
||||
// -----BEGIN MALFORMED BLOCK-----
|
||||
// junk that may look like header lines
|
||||
// or data lines, but no END line
|
||||
//
|
||||
// -----BEGIN ACTUAL BLOCK-----
|
||||
// realdata
|
||||
// -----END ACTUAL BLOCK-----
|
||||
//
|
||||
// we've failed to parse using the first BEGIN line
|
||||
// and now will try again, using the second BEGIN line.
|
||||
p, rest := Decode(rest)
|
||||
if p == nil {
|
||||
rest = data
|
||||
}
|
||||
return p, rest
|
||||
}
|
||||
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig#L20-L21
|
||||
// Should be on 76 chars, but strangely enough ssh breaks on 70
|
||||
const pemLineLength = 70
|
||||
|
||||
type lineBreaker struct {
|
||||
line [pemLineLength]byte
|
||||
used int
|
||||
out io.Writer
|
||||
}
|
||||
|
||||
var nl = []byte{'\n'}
|
||||
|
||||
func (l *lineBreaker) Write(b []byte) (n int, err error) {
|
||||
if l.used+len(b) < pemLineLength {
|
||||
copy(l.line[l.used:], b)
|
||||
l.used += len(b)
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
n, err = l.out.Write(l.line[0:l.used])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
excess := pemLineLength - l.used
|
||||
l.used = 0
|
||||
|
||||
n, err = l.out.Write(b[0:excess])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
n, err = l.out.Write(nl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return l.Write(b[excess:])
|
||||
}
|
||||
|
||||
func (l *lineBreaker) Close() (err error) {
|
||||
if l.used > 0 {
|
||||
_, err = l.out.Write(l.line[0:l.used])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = l.out.Write(nl)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func writeHeader(out io.Writer, k, v string) error {
|
||||
_, err := out.Write([]byte(k + ": " + v + "\n"))
|
||||
return err
|
||||
}
|
||||
|
||||
// Encode writes the PEM encoding of b to out.
|
||||
func Encode(out io.Writer, b *Block) error {
|
||||
// Check for invalid block before writing any output.
|
||||
for k := range b.Headers {
|
||||
if strings.Contains(k, ":") {
|
||||
return errors.New("pem: cannot encode a header key that contains a colon")
|
||||
}
|
||||
}
|
||||
|
||||
// All errors below are relayed from underlying io.Writer,
|
||||
// so it is now safe to write data.
|
||||
|
||||
if _, err := out.Write(pemStart[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := out.Write([]byte(b.Type + "-----\n")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(b.Headers) > 0 {
|
||||
const procType = "Proc-Type"
|
||||
h := make([]string, 0, len(b.Headers))
|
||||
hasProcType := false
|
||||
for k := range b.Headers {
|
||||
if k == procType {
|
||||
hasProcType = true
|
||||
continue
|
||||
}
|
||||
h = append(h, k)
|
||||
}
|
||||
// The Proc-Type header must be written first.
|
||||
// See RFC 1421, section 4.6.1.1
|
||||
if hasProcType {
|
||||
if err := writeHeader(out, procType, b.Headers[procType]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// For consistency of output, write other headers sorted by key.
|
||||
sort.Strings(h)
|
||||
for _, k := range h {
|
||||
if err := writeHeader(out, k, b.Headers[k]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err := out.Write(nl); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var breaker lineBreaker
|
||||
breaker.out = out
|
||||
|
||||
b64 := base64.NewEncoder(base64.StdEncoding, &breaker)
|
||||
if _, err := b64.Write(b.Bytes); err != nil {
|
||||
return err
|
||||
}
|
||||
b64.Close()
|
||||
breaker.Close()
|
||||
|
||||
if _, err := out.Write(pemEnd[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := out.Write([]byte(b.Type + "-----\n"))
|
||||
return err
|
||||
}
|
||||
|
||||
// EncodeToMemory returns the PEM encoding of b.
|
||||
//
|
||||
// If b has invalid headers and cannot be encoded,
|
||||
// EncodeToMemory returns nil. If it is important to
|
||||
// report details about this error case, use Encode instead.
|
||||
func EncodeToMemory(b *Block) []byte {
|
||||
var buf bytes.Buffer
|
||||
if err := Encode(&buf, b); err != nil {
|
||||
return nil
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// Modifications by 42wim
|
||||
//
|
||||
// Copyright 2021 The Sigstore Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sshsig
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig#L81
|
||||
type MessageWrapper struct {
|
||||
Namespace string
|
||||
Reserved string
|
||||
HashAlgorithm string
|
||||
Hash string
|
||||
}
|
||||
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig#L34
|
||||
type WrappedSig struct {
|
||||
MagicHeader [6]byte
|
||||
Version uint32
|
||||
PublicKey string
|
||||
Namespace string
|
||||
Reserved string
|
||||
HashAlgorithm string
|
||||
Signature string
|
||||
}
|
||||
|
||||
const (
|
||||
magicHeader = "SSHSIG"
|
||||
defaultHashAlgorithm = "sha512"
|
||||
)
|
||||
|
||||
var supportedHashAlgorithms = map[string]func() hash.Hash{
|
||||
"sha256": sha256.New,
|
||||
"sha512": sha512.New,
|
||||
}
|
||||
|
||||
func wrapData(m io.Reader, ns string) ([]byte, error) {
|
||||
hf := sha512.New()
|
||||
if _, err := io.Copy(hf, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mh := hf.Sum(nil)
|
||||
|
||||
sp := MessageWrapper{
|
||||
Namespace: ns,
|
||||
HashAlgorithm: defaultHashAlgorithm,
|
||||
Hash: string(mh),
|
||||
}
|
||||
|
||||
dataMessageWrapper := ssh.Marshal(sp)
|
||||
dataMessageWrapper = append([]byte(magicHeader), dataMessageWrapper...)
|
||||
|
||||
return dataMessageWrapper, nil
|
||||
}
|
||||
|
||||
func sign(s ssh.AlgorithmSigner, m io.Reader, ns string) (*ssh.Signature, error) {
|
||||
dataMessageWrapper, err := wrapData(m, ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// ssh-rsa is not supported for RSA keys:
|
||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig#L71
|
||||
// We can use the default value of "" for other key types though.
|
||||
algo := ""
|
||||
if s.PublicKey().Type() == ssh.KeyAlgoRSA {
|
||||
algo = ssh.SigAlgoRSASHA2512
|
||||
}
|
||||
|
||||
return s.SignWithAlgorithm(rand.Reader, dataMessageWrapper, algo)
|
||||
}
|
||||
|
||||
func signAgent(pk ssh.PublicKey, ag agent.Agent, m io.Reader, ns string) (*ssh.Signature, error) {
|
||||
dataMessageWrapper, err := wrapData(m, ns)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sigFlag agent.SignatureFlags
|
||||
if pk.Type() == ssh.KeyAlgoRSA {
|
||||
sigFlag = agent.SignatureFlagRsaSha512
|
||||
}
|
||||
|
||||
agExt, ok := ag.(agent.ExtendedAgent)
|
||||
if !ok {
|
||||
return nil, errors.New("couldn't cast to ExtendedAgent")
|
||||
}
|
||||
|
||||
return agExt.SignWithFlags(pk, dataMessageWrapper, sigFlag)
|
||||
}
|
||||
|
||||
// SignWithAgent asks the ssh Agent to sign the data with the signer matching the given publicKey and returns an armored signature.
|
||||
// The purpose of the namespace value is to specify a unambiguous
|
||||
// interpretation domain for the signature, e.g. file signing.
|
||||
// This prevents cross-protocol attacks caused by signatures
|
||||
// intended for one intended domain being accepted in another.
|
||||
// If empty, the default is "file".
|
||||
// This can be compared with `ssh-keygen -Y sign -f keyfile -n namespace data`
|
||||
func SignWithAgent(publicKey []byte, ag agent.Agent, data io.Reader, namespace string) ([]byte, error) {
|
||||
pk, _, _, _, err := ssh.ParseAuthorizedKey(publicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if namespace == "" {
|
||||
namespace = defaultNamespace
|
||||
}
|
||||
|
||||
sig, err := signAgent(pk, ag, data, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
armored := Armor(sig, pk, namespace)
|
||||
return armored, nil
|
||||
}
|
||||
|
||||
// Sign signs the data with the given private key in PEM format and returns an armored signature.
|
||||
// The purpose of the namespace value is to specify a unambiguous
|
||||
// interpretation domain for the signature, e.g. file signing.
|
||||
// This prevents cross-protocol attacks caused by signatures
|
||||
// intended for one intended domain being accepted in another.
|
||||
// If empty, the default is "file".
|
||||
// This can be compared with `ssh-keygen -Y sign -f keyfile -n namespace data`
|
||||
func Sign(pemBytes []byte, data io.Reader, namespace string) ([]byte, error) {
|
||||
s, err := ssh.ParsePrivateKey(pemBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
as, ok := s.(ssh.AlgorithmSigner)
|
||||
if !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if namespace == "" {
|
||||
namespace = defaultNamespace
|
||||
}
|
||||
|
||||
sig, err := sign(as, data, namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
armored := Armor(sig, s.PublicKey(), namespace)
|
||||
return armored, nil
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
// modified by 42wim
|
||||
//
|
||||
// Copyright 2021 The Sigstore Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sshsig
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type Signature struct {
|
||||
signature *ssh.Signature
|
||||
pk ssh.PublicKey
|
||||
hashAlg string
|
||||
}
|
||||
|
||||
const defaultNamespace = "file"
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// Copyright 2021 The Sigstore Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sshsig
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// Verify verifies the signature of the given data and the armored signature using the given public key and the namespace.
|
||||
// If the namespace is empty, the default namespace (file) is used.
|
||||
func Verify(message io.Reader, armoredSignature []byte, publicKey []byte, namespace string) error {
|
||||
if namespace == "" {
|
||||
namespace = defaultNamespace
|
||||
}
|
||||
|
||||
decodedSignature, err := Decode(armoredSignature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
desiredPk, _, _, _, err := ssh.ParseAuthorizedKey(publicKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Hash the message so we can verify it against the signature.
|
||||
h := supportedHashAlgorithms[decodedSignature.hashAlg]()
|
||||
if _, err := io.Copy(h, message); err != nil {
|
||||
return err
|
||||
}
|
||||
hm := h.Sum(nil)
|
||||
|
||||
toVerify := MessageWrapper{
|
||||
Namespace: namespace,
|
||||
HashAlgorithm: decodedSignature.hashAlg,
|
||||
Hash: string(hm),
|
||||
}
|
||||
signedMessage := ssh.Marshal(toVerify)
|
||||
signedMessage = append([]byte(magicHeader), signedMessage...)
|
||||
return desiredPk.Verify(signedMessage, decodedSignature.signature)
|
||||
}
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+1
-1
@@ -15,7 +15,7 @@
|
||||
// used with a fixed key in order to generate one-time keys from an nonce.
|
||||
// However, in this package AES isn't used and the one-time key is specified
|
||||
// directly.
|
||||
package poly1305 // import "golang.org/x/crypto/poly1305"
|
||||
package poly1305
|
||||
|
||||
import "crypto/subtle"
|
||||
|
||||
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
File renamed without changes.
Generated
Vendored
+1
-1
@@ -18,7 +18,7 @@
|
||||
// value. These limbs are, for the most part, zero extended and
|
||||
// placed into 64-bit vector register elements. Each vector
|
||||
// register is 128-bits wide and so holds 2 of these elements.
|
||||
// Using 26-bit limbs allows us plenty of headroom to accomodate
|
||||
// Using 26-bit limbs allows us plenty of headroom to accommodate
|
||||
// accumulations before and after multiplication without
|
||||
// overflowing either 32-bits (before multiplication) or 64-bits
|
||||
// (after multiplication).
|
||||
+22
-2
@@ -14,7 +14,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// These constants from [PROTOCOL.certkeys] represent the algorithm names
|
||||
// These constants from [PROTOCOL.certkeys] represent the key algorithm names
|
||||
// for certificate types supported by this package.
|
||||
const (
|
||||
CertAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
|
||||
@@ -27,6 +27,14 @@ const (
|
||||
CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"
|
||||
)
|
||||
|
||||
// These constants from [PROTOCOL.certkeys] represent additional signature
|
||||
// algorithm names for certificate types supported by this package.
|
||||
const (
|
||||
CertSigAlgoRSAv01 = "ssh-rsa-cert-v01@openssh.com"
|
||||
CertSigAlgoRSASHA2256v01 = "rsa-sha2-256-cert-v01@openssh.com"
|
||||
CertSigAlgoRSASHA2512v01 = "rsa-sha2-512-cert-v01@openssh.com"
|
||||
)
|
||||
|
||||
// Certificate types distinguish between host and user
|
||||
// certificates. The values can be set in the CertType field of
|
||||
// Certificate.
|
||||
@@ -423,6 +431,12 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
|
||||
}
|
||||
c.SignatureKey = authority.PublicKey()
|
||||
|
||||
if v, ok := authority.(AlgorithmSigner); ok {
|
||||
if v.PublicKey().Type() == KeyAlgoRSA {
|
||||
authority = &rsaSigner{v, SigAlgoRSASHA2512}
|
||||
}
|
||||
}
|
||||
|
||||
sig, err := authority.Sign(rand, c.bytesForSigning())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -431,8 +445,14 @@ func (c *Certificate) SignCert(rand io.Reader, authority Signer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// certAlgoNames includes a mapping from signature algorithms to the
|
||||
// corresponding certificate signature algorithm. When a key type (such
|
||||
// as ED25516) is associated with only one algorithm, the KeyAlgo
|
||||
// constant is used instead of the SigAlgo.
|
||||
var certAlgoNames = map[string]string{
|
||||
KeyAlgoRSA: CertAlgoRSAv01,
|
||||
SigAlgoRSA: CertSigAlgoRSAv01,
|
||||
SigAlgoRSASHA2256: CertSigAlgoRSASHA2256v01,
|
||||
SigAlgoRSASHA2512: CertSigAlgoRSASHA2512v01,
|
||||
KeyAlgoDSA: CertAlgoDSAv01,
|
||||
KeyAlgoECDSA256: CertAlgoECDSA256v01,
|
||||
KeyAlgoECDSA384: CertAlgoECDSA384v01,
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"golang.org/x/crypto/chacha20"
|
||||
"golang.org/x/crypto/poly1305"
|
||||
"golang.org/x/crypto/internal/poly1305"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
+14
-1
@@ -115,12 +115,25 @@ func (c *connection) clientHandshake(dialAddress string, config *ClientConfig) e
|
||||
|
||||
// verifyHostKeySignature verifies the host key obtained in the key
|
||||
// exchange.
|
||||
func verifyHostKeySignature(hostKey PublicKey, result *kexResult) error {
|
||||
func verifyHostKeySignature(hostKey PublicKey, algo string, result *kexResult) error {
|
||||
sig, rest, ok := parseSignatureBody(result.Signature)
|
||||
if len(rest) > 0 || !ok {
|
||||
return errors.New("ssh: signature parse error")
|
||||
}
|
||||
|
||||
// For keys, underlyingAlgo is exactly algo. For certificates,
|
||||
// we have to look up the underlying key algorithm that SSH
|
||||
// uses to evaluate signatures.
|
||||
underlyingAlgo := algo
|
||||
for sigAlgo, certAlgo := range certAlgoNames {
|
||||
if certAlgo == algo {
|
||||
underlyingAlgo = sigAlgo
|
||||
}
|
||||
}
|
||||
if sig.Format != underlyingAlgo {
|
||||
return fmt.Errorf("ssh: invalid signature algorithm %q, expected %q", sig.Format, underlyingAlgo)
|
||||
}
|
||||
|
||||
return hostKey.Verify(result.H, sig)
|
||||
}
|
||||
|
||||
|
||||
+18
-12
@@ -69,11 +69,13 @@ var preferredKexAlgos = []string{
|
||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||
// of authenticating servers) in preference order.
|
||||
var supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01,
|
||||
CertSigAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
||||
|
||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||
KeyAlgoRSA, KeyAlgoDSA,
|
||||
SigAlgoRSASHA2512, SigAlgoRSASHA2256,
|
||||
SigAlgoRSA, KeyAlgoDSA,
|
||||
|
||||
KeyAlgoED25519,
|
||||
}
|
||||
@@ -90,16 +92,20 @@ var supportedCompressions = []string{compressionNone}
|
||||
// hashFuncs keeps the mapping of supported algorithms to their respective
|
||||
// hashes needed for signature verification.
|
||||
var hashFuncs = map[string]crypto.Hash{
|
||||
KeyAlgoRSA: crypto.SHA1,
|
||||
KeyAlgoDSA: crypto.SHA1,
|
||||
KeyAlgoECDSA256: crypto.SHA256,
|
||||
KeyAlgoECDSA384: crypto.SHA384,
|
||||
KeyAlgoECDSA521: crypto.SHA512,
|
||||
CertAlgoRSAv01: crypto.SHA1,
|
||||
CertAlgoDSAv01: crypto.SHA1,
|
||||
CertAlgoECDSA256v01: crypto.SHA256,
|
||||
CertAlgoECDSA384v01: crypto.SHA384,
|
||||
CertAlgoECDSA521v01: crypto.SHA512,
|
||||
SigAlgoRSA: crypto.SHA1,
|
||||
SigAlgoRSASHA2256: crypto.SHA256,
|
||||
SigAlgoRSASHA2512: crypto.SHA512,
|
||||
KeyAlgoDSA: crypto.SHA1,
|
||||
KeyAlgoECDSA256: crypto.SHA256,
|
||||
KeyAlgoECDSA384: crypto.SHA384,
|
||||
KeyAlgoECDSA521: crypto.SHA512,
|
||||
CertSigAlgoRSAv01: crypto.SHA1,
|
||||
CertSigAlgoRSASHA2256v01: crypto.SHA256,
|
||||
CertSigAlgoRSASHA2512v01: crypto.SHA512,
|
||||
CertAlgoDSAv01: crypto.SHA1,
|
||||
CertAlgoECDSA256v01: crypto.SHA256,
|
||||
CertAlgoECDSA384v01: crypto.SHA384,
|
||||
CertAlgoECDSA521v01: crypto.SHA512,
|
||||
}
|
||||
|
||||
// unexpectedMessageError results when the SSH message that we received didn't
|
||||
|
||||
+25
-4
@@ -457,8 +457,15 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||
|
||||
if len(t.hostKeys) > 0 {
|
||||
for _, k := range t.hostKeys {
|
||||
msg.ServerHostKeyAlgos = append(
|
||||
msg.ServerHostKeyAlgos, k.PublicKey().Type())
|
||||
algo := k.PublicKey().Type()
|
||||
switch algo {
|
||||
case KeyAlgoRSA:
|
||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{SigAlgoRSASHA2512, SigAlgoRSASHA2256, SigAlgoRSA}...)
|
||||
case CertAlgoRSAv01:
|
||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, []string{CertSigAlgoRSASHA2512v01, CertSigAlgoRSASHA2256v01, CertSigAlgoRSAv01}...)
|
||||
default:
|
||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
|
||||
@@ -614,8 +621,22 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||
func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) {
|
||||
var hostKey Signer
|
||||
for _, k := range t.hostKeys {
|
||||
if algs.hostKey == k.PublicKey().Type() {
|
||||
kt := k.PublicKey().Type()
|
||||
if kt == algs.hostKey {
|
||||
hostKey = k
|
||||
} else if signer, ok := k.(AlgorithmSigner); ok {
|
||||
// Some signature algorithms don't show up as key types
|
||||
// so we have to manually check for a compatible host key.
|
||||
switch kt {
|
||||
case KeyAlgoRSA:
|
||||
if algs.hostKey == SigAlgoRSASHA2256 || algs.hostKey == SigAlgoRSASHA2512 {
|
||||
hostKey = &rsaSigner{signer, algs.hostKey}
|
||||
}
|
||||
case CertAlgoRSAv01:
|
||||
if algs.hostKey == CertSigAlgoRSASHA2256v01 || algs.hostKey == CertSigAlgoRSASHA2512v01 {
|
||||
hostKey = &rsaSigner{signer, certToPrivAlgo(algs.hostKey)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,7 +655,7 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := verifyHostKeySignature(hostKey, result); err != nil {
|
||||
if err := verifyHostKeySignature(hostKey, algs.hostKey, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -939,6 +939,15 @@ func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
|
||||
return &dsaPrivateKey{key}, nil
|
||||
}
|
||||
|
||||
type rsaSigner struct {
|
||||
AlgorithmSigner
|
||||
defaultAlgorithm string
|
||||
}
|
||||
|
||||
func (s *rsaSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
|
||||
return s.AlgorithmSigner.SignWithAlgorithm(rand, data, s.defaultAlgorithm)
|
||||
}
|
||||
|
||||
type wrappedSigner struct {
|
||||
signer crypto.Signer
|
||||
pubKey PublicKey
|
||||
|
||||
+1
-1
@@ -284,7 +284,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
||||
|
||||
func isAcceptableAlgo(algo string) bool {
|
||||
switch algo {
|
||||
case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
|
||||
case SigAlgoRSA, SigAlgoRSASHA2256, SigAlgoRSASHA2512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
|
||||
return true
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package idna
|
||||
|
||||
// Transitional processing is disabled by default in Go 1.18.
|
||||
// https://golang.org/issue/47510
|
||||
const transitionalLookup = false
|
||||
+3
-3
@@ -59,10 +59,10 @@ type Option func(*options)
|
||||
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||
// compatibility. It is used by most browsers when resolving domain names. This
|
||||
// compatibility. It is used by some browsers when resolving domain names. This
|
||||
// option is only meaningful if combined with MapForLookup.
|
||||
func Transitional(transitional bool) Option {
|
||||
return func(o *options) { o.transitional = true }
|
||||
return func(o *options) { o.transitional = transitional }
|
||||
}
|
||||
|
||||
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||
@@ -284,7 +284,7 @@ var (
|
||||
|
||||
punycode = &Profile{}
|
||||
lookup = &Profile{options{
|
||||
transitional: true,
|
||||
transitional: transitionalLookup,
|
||||
useSTD3Rules: true,
|
||||
checkHyphens: true,
|
||||
checkJoiners: true,
|
||||
|
||||
+2
-2
@@ -58,10 +58,10 @@ type Option func(*options)
|
||||
// Transitional sets a Profile to use the Transitional mapping as defined in UTS
|
||||
// #46. This will cause, for example, "ß" to be mapped to "ss". Using the
|
||||
// transitional mapping provides a compromise between IDNA2003 and IDNA2008
|
||||
// compatibility. It is used by most browsers when resolving domain names. This
|
||||
// compatibility. It is used by some browsers when resolving domain names. This
|
||||
// option is only meaningful if combined with MapForLookup.
|
||||
func Transitional(transitional bool) Option {
|
||||
return func(o *options) { o.transitional = true }
|
||||
return func(o *options) { o.transitional = transitional }
|
||||
}
|
||||
|
||||
// VerifyDNSLength sets whether a Profile should fail if any of the IDN parts
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Code generated by running "go generate" in golang.org/x/text. DO NOT EDIT.
|
||||
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package idna
|
||||
|
||||
const transitionalLookup = true
|
||||
+25
-11
@@ -49,6 +49,7 @@ func decode(encoded string) (string, error) {
|
||||
}
|
||||
}
|
||||
i, n, bias := int32(0), initialN, initialBias
|
||||
overflow := false
|
||||
for pos < len(encoded) {
|
||||
oldI, w := i, int32(1)
|
||||
for k := base; ; k += base {
|
||||
@@ -60,29 +61,32 @@ func decode(encoded string) (string, error) {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
pos++
|
||||
i += digit * w
|
||||
if i < 0 {
|
||||
i, overflow = madd(i, digit, w)
|
||||
if overflow {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
t := k - bias
|
||||
if t < tmin {
|
||||
if k <= bias {
|
||||
t = tmin
|
||||
} else if t > tmax {
|
||||
} else if k >= bias+tmax {
|
||||
t = tmax
|
||||
}
|
||||
if digit < t {
|
||||
break
|
||||
}
|
||||
w *= base - t
|
||||
if w >= math.MaxInt32/base {
|
||||
w, overflow = madd(0, w, base-t)
|
||||
if overflow {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
}
|
||||
if len(output) >= 1024 {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
x := int32(len(output) + 1)
|
||||
bias = adapt(i-oldI, x, oldI == 0)
|
||||
n += i / x
|
||||
i %= x
|
||||
if n > utf8.MaxRune || len(output) >= 1024 {
|
||||
if n < 0 || n > utf8.MaxRune {
|
||||
return "", punyError(encoded)
|
||||
}
|
||||
output = append(output, 0)
|
||||
@@ -115,6 +119,7 @@ func encode(prefix, s string) (string, error) {
|
||||
if b > 0 {
|
||||
output = append(output, '-')
|
||||
}
|
||||
overflow := false
|
||||
for remaining != 0 {
|
||||
m := int32(0x7fffffff)
|
||||
for _, r := range s {
|
||||
@@ -122,8 +127,8 @@ func encode(prefix, s string) (string, error) {
|
||||
m = r
|
||||
}
|
||||
}
|
||||
delta += (m - n) * (h + 1)
|
||||
if delta < 0 {
|
||||
delta, overflow = madd(delta, m-n, h+1)
|
||||
if overflow {
|
||||
return "", punyError(s)
|
||||
}
|
||||
n = m
|
||||
@@ -141,9 +146,9 @@ func encode(prefix, s string) (string, error) {
|
||||
q := delta
|
||||
for k := base; ; k += base {
|
||||
t := k - bias
|
||||
if t < tmin {
|
||||
if k <= bias {
|
||||
t = tmin
|
||||
} else if t > tmax {
|
||||
} else if k >= bias+tmax {
|
||||
t = tmax
|
||||
}
|
||||
if q < t {
|
||||
@@ -164,6 +169,15 @@ func encode(prefix, s string) (string, error) {
|
||||
return string(output), nil
|
||||
}
|
||||
|
||||
// madd computes a + (b * c), detecting overflow.
|
||||
func madd(a, b, c int32) (next int32, overflow bool) {
|
||||
p := int64(b) * int64(c)
|
||||
if p > math.MaxInt32-int64(a) {
|
||||
return 0, true
|
||||
}
|
||||
return a + int32(p), false
|
||||
}
|
||||
|
||||
func decodeDigit(x byte) (digit int32, ok bool) {
|
||||
switch {
|
||||
case '0' <= x && x <= '9':
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && go1.12
|
||||
// +build darwin,go1.12
|
||||
|
||||
// This exists solely so we can linkname in symbols from syscall.
|
||||
+10391
-10349
File diff suppressed because it is too large.
Load diff
+4
-3
@@ -90,9 +90,10 @@ func archInit() {
|
||||
osSupportsAVX = isSet(1, eax) && isSet(2, eax)
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
// Check darwin commpage for AVX512 support. Necessary because:
|
||||
// https://github.com/apple/darwin-xnu/blob/0a798f6738bc1db01281fc08ae024145e84df927/osfmk/i386/fpu.c#L175-L201
|
||||
osSupportsAVX512 = osSupportsAVX && darwinSupportsAVX512()
|
||||
// Darwin doesn't save/restore AVX-512 mask registers correctly across signal handlers.
|
||||
// Since users can't rely on mask register contents, let's not advertise AVX-512 support.
|
||||
// See issue 49233.
|
||||
osSupportsAVX512 = false
|
||||
} else {
|
||||
// Check if OPMASK and ZMM registers have OS support.
|
||||
osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax)
|
||||
|
||||
-24
@@ -26,27 +26,3 @@ TEXT ·xgetbv(SB),NOSPLIT,$0-8
|
||||
MOVL AX, eax+0(FP)
|
||||
MOVL DX, edx+4(FP)
|
||||
RET
|
||||
|
||||
// func darwinSupportsAVX512() bool
|
||||
TEXT ·darwinSupportsAVX512(SB), NOSPLIT, $0-1
|
||||
MOVB $0, ret+0(FP) // default to false
|
||||
#ifdef GOOS_darwin // return if not darwin
|
||||
#ifdef GOARCH_amd64 // return if not amd64
|
||||
// These values from:
|
||||
// https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/osfmk/i386/cpu_capabilities.h
|
||||
#define commpage64_base_address 0x00007fffffe00000
|
||||
#define commpage64_cpu_capabilities64 (commpage64_base_address+0x010)
|
||||
#define commpage64_version (commpage64_base_address+0x01E)
|
||||
#define hasAVX512F 0x0000004000000000
|
||||
MOVQ $commpage64_version, BX
|
||||
CMPW (BX), $13 // cpu_capabilities64 undefined in versions < 13
|
||||
JL no_avx512
|
||||
MOVQ $commpage64_cpu_capabilities64, BX
|
||||
MOVQ $hasAVX512F, CX
|
||||
TESTQ (BX), CX
|
||||
JZ no_avx512
|
||||
MOVB $1, ret+0(FP)
|
||||
no_avx512:
|
||||
#endif
|
||||
#endif
|
||||
RET
|
||||
+1
-1
@@ -149,7 +149,7 @@ To add a constant, add the header that includes it to the appropriate variable.
|
||||
Then, edit the regex (if necessary) to match the desired constant. Avoid making
|
||||
the regex too broad to avoid matching unintended constants.
|
||||
|
||||
### mkmerge.go
|
||||
### internal/mkmerge
|
||||
|
||||
This program is used to extract duplicate const, func, and type declarations
|
||||
from the generated architecture-specific files listed below, and merge these
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ if [[ "$GOOS" = "linux" ]]; then
|
||||
# Use the Docker-based build system
|
||||
# Files generated through docker (use $cmd so you can Ctl-C the build or run)
|
||||
$cmd docker build --tag generate:$GOOS $GOOS
|
||||
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")" && /bin/pwd):/build generate:$GOOS
|
||||
$cmd docker run --interactive --tty --volume $(cd -- "$(dirname -- "$0")/.." && /bin/pwd):/build generate:$GOOS
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
+9
-3
@@ -54,7 +54,7 @@ includes_AIX='
|
||||
|
||||
includes_Darwin='
|
||||
#define _DARWIN_C_SOURCE
|
||||
#define KERNEL
|
||||
#define KERNEL 1
|
||||
#define _DARWIN_USE_64_BIT_INODE
|
||||
#define __APPLE_USE_RFC_3542
|
||||
#include <stdint.h>
|
||||
@@ -75,6 +75,7 @@ includes_Darwin='
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <sys/vsock.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_types.h>
|
||||
@@ -82,6 +83,9 @@ includes_Darwin='
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <termios.h>
|
||||
|
||||
// for backwards compatibility because moved TIOCREMOTE to Kernel.framework after MacOSX12.0.sdk.
|
||||
#define TIOCREMOTE 0x80047469
|
||||
'
|
||||
|
||||
includes_DragonFly='
|
||||
@@ -229,11 +233,13 @@ struct ltchars {
|
||||
#include <linux/input.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/keyctl.h>
|
||||
#include <linux/landlock.h>
|
||||
#include <linux/loop.h>
|
||||
#include <linux/lwtunnel.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/memfd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/net_namespace.h>
|
||||
@@ -465,7 +471,6 @@ ccflags="$@"
|
||||
$2 !~ /^EQUIV_/ &&
|
||||
$2 !~ /^EXPR_/ &&
|
||||
$2 !~ /^EVIOC/ &&
|
||||
$2 !~ /^EV_/ &&
|
||||
$2 ~ /^E[A-Z0-9_]+$/ ||
|
||||
$2 ~ /^B[0-9_]+$/ ||
|
||||
$2 ~ /^(OLD|NEW)DEV$/ ||
|
||||
@@ -497,6 +502,7 @@ ccflags="$@"
|
||||
$2 ~ /^O?XTABS$/ ||
|
||||
$2 ~ /^TC[IO](ON|OFF)$/ ||
|
||||
$2 ~ /^IN_/ ||
|
||||
$2 ~ /^LANDLOCK_/ ||
|
||||
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
|
||||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
|
||||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
|
||||
@@ -515,7 +521,7 @@ ccflags="$@"
|
||||
$2 ~ /^HW_MACHINE$/ ||
|
||||
$2 ~ /^SYSCTL_VERS/ ||
|
||||
$2 !~ "MNT_BITS" &&
|
||||
$2 ~ /^(MS|MNT|UMOUNT)_/ ||
|
||||
$2 ~ /^(MS|MNT|MOUNT|UMOUNT)_/ ||
|
||||
$2 ~ /^NS_GET_/ ||
|
||||
$2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ ||
|
||||
$2 ~ /^(O|F|[ES]?FD|NAME|S|PTRACE|PT|TFD)_/ ||
|
||||
|
||||
+49
@@ -34,3 +34,52 @@ func ParseUnixCredentials(m *SocketControlMessage) (*Ucred, error) {
|
||||
ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
|
||||
return &ucred, nil
|
||||
}
|
||||
|
||||
// PktInfo4 encodes Inet4Pktinfo into a socket control message of type IP_PKTINFO.
|
||||
func PktInfo4(info *Inet4Pktinfo) []byte {
|
||||
b := make([]byte, CmsgSpace(SizeofInet4Pktinfo))
|
||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||
h.Level = SOL_IP
|
||||
h.Type = IP_PKTINFO
|
||||
h.SetLen(CmsgLen(SizeofInet4Pktinfo))
|
||||
*(*Inet4Pktinfo)(h.data(0)) = *info
|
||||
return b
|
||||
}
|
||||
|
||||
// PktInfo6 encodes Inet6Pktinfo into a socket control message of type IPV6_PKTINFO.
|
||||
func PktInfo6(info *Inet6Pktinfo) []byte {
|
||||
b := make([]byte, CmsgSpace(SizeofInet6Pktinfo))
|
||||
h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
|
||||
h.Level = SOL_IPV6
|
||||
h.Type = IPV6_PKTINFO
|
||||
h.SetLen(CmsgLen(SizeofInet6Pktinfo))
|
||||
*(*Inet6Pktinfo)(h.data(0)) = *info
|
||||
return b
|
||||
}
|
||||
|
||||
// ParseOrigDstAddr decodes a socket control message containing the original
|
||||
// destination address. To receive such a message the IP_RECVORIGDSTADDR or
|
||||
// IPV6_RECVORIGDSTADDR option must be enabled on the socket.
|
||||
func ParseOrigDstAddr(m *SocketControlMessage) (Sockaddr, error) {
|
||||
switch {
|
||||
case m.Header.Level == SOL_IP && m.Header.Type == IP_ORIGDSTADDR:
|
||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(&m.Data[0]))
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case m.Header.Level == SOL_IPV6 && m.Header.Type == IPV6_ORIGDSTADDR:
|
||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(&m.Data[0]))
|
||||
sa := new(SockaddrInet6)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
default:
|
||||
return nil, EINVAL
|
||||
}
|
||||
}
|
||||
+9
-13
@@ -70,9 +70,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
|
||||
}
|
||||
|
||||
@@ -85,9 +83,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
|
||||
}
|
||||
|
||||
@@ -261,9 +257,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case AF_INET6:
|
||||
@@ -272,9 +266,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
@@ -385,6 +377,11 @@ func (w WaitStatus) TrapCause() int { return -1 }
|
||||
|
||||
//sys fcntl(fd int, cmd int, arg int) (val int, err error)
|
||||
|
||||
//sys fsyncRange(fd int, how int, start int64, length int64) (err error) = fsync_range
|
||||
func Fsync(fd int) error {
|
||||
return fsyncRange(fd, O_SYNC, 0, 0)
|
||||
}
|
||||
|
||||
/*
|
||||
* Direct access
|
||||
*/
|
||||
@@ -401,7 +398,6 @@ func (w WaitStatus) TrapCause() int { return -1 }
|
||||
//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
|
||||
//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
|
||||
//sys Fdatasync(fd int) (err error)
|
||||
//sys Fsync(fd int) (err error)
|
||||
// readdir_r
|
||||
//sysnb Getpgid(pid int) (pgid int, err error)
|
||||
|
||||
|
||||
+6
-18
@@ -163,9 +163,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
|
||||
}
|
||||
|
||||
@@ -179,9 +177,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
|
||||
}
|
||||
|
||||
@@ -210,9 +206,7 @@ func (sa *SockaddrDatalink) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Nlen = sa.Nlen
|
||||
sa.raw.Alen = sa.Alen
|
||||
sa.raw.Slen = sa.Slen
|
||||
for i := 0; i < len(sa.raw.Data); i++ {
|
||||
sa.raw.Data[i] = sa.Data[i]
|
||||
}
|
||||
sa.raw.Data = sa.Data
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrDatalink, nil
|
||||
}
|
||||
|
||||
@@ -228,9 +222,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa.Nlen = pp.Nlen
|
||||
sa.Alen = pp.Alen
|
||||
sa.Slen = pp.Slen
|
||||
for i := 0; i < len(sa.Data); i++ {
|
||||
sa.Data[i] = pp.Data[i]
|
||||
}
|
||||
sa.Data = pp.Data
|
||||
return sa, nil
|
||||
|
||||
case AF_UNIX:
|
||||
@@ -262,9 +254,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case AF_INET6:
|
||||
@@ -273,9 +263,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
return anyToSockaddrGOOS(fd, rsa)
|
||||
|
||||
+55
-6
@@ -48,6 +48,30 @@ func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil
|
||||
}
|
||||
|
||||
// SockaddrVM implements the Sockaddr interface for AF_VSOCK type sockets.
|
||||
// SockaddrVM provides access to Darwin VM sockets: a mechanism that enables
|
||||
// bidirectional communication between a hypervisor and its guest virtual
|
||||
// machines.
|
||||
type SockaddrVM struct {
|
||||
// CID and Port specify a context ID and port address for a VM socket.
|
||||
// Guests have a unique CID, and hosts may have a well-known CID of:
|
||||
// - VMADDR_CID_HYPERVISOR: refers to the hypervisor process.
|
||||
// - VMADDR_CID_LOCAL: refers to local communication (loopback).
|
||||
// - VMADDR_CID_HOST: refers to other processes on the host.
|
||||
CID uint32
|
||||
Port uint32
|
||||
raw RawSockaddrVM
|
||||
}
|
||||
|
||||
func (sa *SockaddrVM) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Len = SizeofSockaddrVM
|
||||
sa.raw.Family = AF_VSOCK
|
||||
sa.raw.Port = sa.Port
|
||||
sa.raw.Cid = sa.CID
|
||||
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrVM, nil
|
||||
}
|
||||
|
||||
func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
switch rsa.Addr.Family {
|
||||
case AF_SYSTEM:
|
||||
@@ -58,6 +82,13 @@ func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa.Unit = pp.Sc_unit
|
||||
return sa, nil
|
||||
}
|
||||
case AF_VSOCK:
|
||||
pp := (*RawSockaddrVM)(unsafe.Pointer(rsa))
|
||||
sa := &SockaddrVM{
|
||||
CID: pp.Cid,
|
||||
Port: pp.Port,
|
||||
}
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
}
|
||||
@@ -399,8 +430,25 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
|
||||
return x, err
|
||||
}
|
||||
|
||||
func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
|
||||
mib, err := sysctlmib(name)
|
||||
func SysctlKinfoProc(name string, args ...int) (*KinfoProc, error) {
|
||||
mib, err := sysctlmib(name, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var kinfo KinfoProc
|
||||
n := uintptr(SizeofKinfoProc)
|
||||
if err := sysctl(mib, (*byte)(unsafe.Pointer(&kinfo)), &n, nil, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != SizeofKinfoProc {
|
||||
return nil, EIO
|
||||
}
|
||||
return &kinfo, nil
|
||||
}
|
||||
|
||||
func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) {
|
||||
mib, err := sysctlmib(name, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -433,6 +481,11 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
|
||||
|
||||
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
|
||||
|
||||
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
|
||||
//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error)
|
||||
//sys shmdt(addr uintptr) (err error)
|
||||
//sys shmget(key int, size int, flag int) (id int, err error)
|
||||
|
||||
/*
|
||||
* Exposed directly
|
||||
*/
|
||||
@@ -590,10 +643,6 @@ func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
|
||||
// Msgget
|
||||
// Msgsnd
|
||||
// Msgrcv
|
||||
// Shmat
|
||||
// Shmctl
|
||||
// Shmdt
|
||||
// Shmget
|
||||
// Shm_open
|
||||
// Shm_unlink
|
||||
// Sem_open
|
||||
|
||||
+8
@@ -162,6 +162,14 @@ func (l *Lifreq) GetLifruInt() int {
|
||||
return *(*int)(unsafe.Pointer(&l.Lifru[0]))
|
||||
}
|
||||
|
||||
func (l *Lifreq) SetLifruUint(d uint) {
|
||||
*(*uint)(unsafe.Pointer(&l.Lifru[0])) = d
|
||||
}
|
||||
|
||||
func (l *Lifreq) GetLifruUint() uint {
|
||||
return *(*uint)(unsafe.Pointer(&l.Lifru[0]))
|
||||
}
|
||||
|
||||
func IoctlLifreq(fd int, req uint, l *Lifreq) error {
|
||||
return ioctl(fd, req, uintptr(unsafe.Pointer(l)))
|
||||
}
|
||||
|
||||
+67
-67
@@ -13,7 +13,6 @@ package unix
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -38,6 +37,13 @@ func Creat(path string, mode uint32) (fd int, err error) {
|
||||
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
|
||||
}
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
if size <= 0 {
|
||||
return -1, EINVAL
|
||||
}
|
||||
return EpollCreate1(0)
|
||||
}
|
||||
|
||||
//sys FanotifyInit(flags uint, event_f_flags uint) (fd int, err error)
|
||||
//sys fanotifyMark(fd int, flags uint, mask uint64, dirFd int, pathname *byte) (err error)
|
||||
|
||||
@@ -66,6 +72,10 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
||||
return fchmodat(dirfd, path, mode)
|
||||
}
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
|
||||
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL
|
||||
|
||||
@@ -109,6 +119,23 @@ func Openat2(dirfd int, path string, how *OpenHow) (fd int, err error) {
|
||||
return openat2(dirfd, path, how, SizeofOpenHow)
|
||||
}
|
||||
|
||||
func Pipe(p []int) error {
|
||||
return Pipe2(p, 0)
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) error {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err := pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return err
|
||||
}
|
||||
|
||||
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error)
|
||||
|
||||
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
|
||||
@@ -118,6 +145,15 @@ func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error
|
||||
return ppoll(&fds[0], len(fds), timeout, sigmask)
|
||||
}
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout >= 0 {
|
||||
ts = new(Timespec)
|
||||
*ts = NsecToTimespec(int64(timeout) * 1e6)
|
||||
}
|
||||
return Ppoll(fds, ts, nil)
|
||||
}
|
||||
|
||||
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
|
||||
|
||||
func Readlink(path string, buf []byte) (n int, err error) {
|
||||
@@ -168,27 +204,7 @@ func Utimes(path string, tv []Timeval) error {
|
||||
//sys utimensat(dirfd int, path string, times *[2]Timespec, flags int) (err error)
|
||||
|
||||
func UtimesNano(path string, ts []Timespec) error {
|
||||
if ts == nil {
|
||||
err := utimensat(AT_FDCWD, path, nil, 0)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
return utimes(path, nil)
|
||||
}
|
||||
if len(ts) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
if err != ENOSYS {
|
||||
return err
|
||||
}
|
||||
// If the utimensat syscall isn't available (utimensat was added to Linux
|
||||
// in 2.6.22, Released, 8 July 2007) then fall back to utimes
|
||||
var tv [2]Timeval
|
||||
for i := 0; i < 2; i++ {
|
||||
tv[i] = NsecToTimeval(TimespecToNsec(ts[i]))
|
||||
}
|
||||
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
|
||||
return UtimesNanoAt(AT_FDCWD, path, ts, 0)
|
||||
}
|
||||
|
||||
func UtimesNanoAt(dirfd int, path string, ts []Timespec, flags int) error {
|
||||
@@ -356,9 +372,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
|
||||
}
|
||||
|
||||
@@ -371,9 +385,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
|
||||
}
|
||||
|
||||
@@ -422,9 +434,7 @@ func (sa *SockaddrLinklayer) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Hatype = sa.Hatype
|
||||
sa.raw.Pkttype = sa.Pkttype
|
||||
sa.raw.Halen = sa.Halen
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrLinklayer, nil
|
||||
}
|
||||
|
||||
@@ -839,12 +849,10 @@ func (sa *SockaddrTIPC) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
if sa.Addr == nil {
|
||||
return nil, 0, EINVAL
|
||||
}
|
||||
|
||||
sa.raw.Family = AF_TIPC
|
||||
sa.raw.Scope = int8(sa.Scope)
|
||||
sa.raw.Addrtype = sa.Addr.tipcAddrtype()
|
||||
sa.raw.Addr = sa.Addr.tipcAddr()
|
||||
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrTIPC, nil
|
||||
}
|
||||
|
||||
@@ -858,9 +866,7 @@ type SockaddrL2TPIP struct {
|
||||
func (sa *SockaddrL2TPIP) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Family = AF_INET
|
||||
sa.raw.Conn_id = sa.ConnId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP, nil
|
||||
}
|
||||
|
||||
@@ -876,9 +882,7 @@ func (sa *SockaddrL2TPIP6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
sa.raw.Family = AF_INET6
|
||||
sa.raw.Conn_id = sa.ConnId
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrL2TPIP6, nil
|
||||
}
|
||||
|
||||
@@ -974,9 +978,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa.Hatype = pp.Hatype
|
||||
sa.Pkttype = pp.Pkttype
|
||||
sa.Halen = pp.Halen
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case AF_UNIX:
|
||||
@@ -1015,18 +1017,14 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
pp := (*RawSockaddrL2TPIP)(unsafe.Pointer(rsa))
|
||||
sa := new(SockaddrL2TPIP)
|
||||
sa.ConnId = pp.Conn_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
default:
|
||||
pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
|
||||
@@ -1042,9 +1040,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa := new(SockaddrL2TPIP6)
|
||||
sa.ConnId = pp.Conn_id
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
default:
|
||||
pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
|
||||
@@ -1052,9 +1048,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
|
||||
@@ -1229,11 +1223,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
func Accept(fd int) (nfd int, sa Sockaddr, err error) {
|
||||
var rsa RawSockaddrAny
|
||||
var len _Socklen = SizeofSockaddrAny
|
||||
// Try accept4 first for Android, then try accept for kernel older than 2.6.28
|
||||
nfd, err = accept4(fd, &rsa, &len, 0)
|
||||
if err == ENOSYS {
|
||||
nfd, err = accept(fd, &rsa, &len)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -1785,6 +1775,16 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
|
||||
return mount(source, target, fstype, flags, datap)
|
||||
}
|
||||
|
||||
//sys mountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr, size uintptr) (err error) = SYS_MOUNT_SETATTR
|
||||
|
||||
// MountSetattr is a wrapper for mount_setattr(2).
|
||||
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
|
||||
//
|
||||
// Requires kernel >= 5.12.
|
||||
func MountSetattr(dirfd int, pathname string, flags uint, attr *MountAttr) error {
|
||||
return mountSetattr(dirfd, pathname, flags, attr, unsafe.Sizeof(*attr))
|
||||
}
|
||||
|
||||
func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
|
||||
if raceenabled {
|
||||
raceReleaseMerge(unsafe.Pointer(&ioSync))
|
||||
@@ -1816,11 +1816,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||
//sys Dup(oldfd int) (fd int, err error)
|
||||
|
||||
func Dup2(oldfd, newfd int) error {
|
||||
// Android O and newer blocks dup2; riscv and arm64 don't implement dup2.
|
||||
if runtime.GOOS == "android" || runtime.GOARCH == "riscv64" || runtime.GOARCH == "arm64" {
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
return dup2(oldfd, newfd)
|
||||
return Dup3(oldfd, newfd, 0)
|
||||
}
|
||||
|
||||
//sys Dup3(oldfd int, newfd int, flags int) (err error)
|
||||
@@ -2308,6 +2304,14 @@ type RemoteIovec struct {
|
||||
//sys ProcessVMReadv(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_READV
|
||||
//sys ProcessVMWritev(pid int, localIov []Iovec, remoteIov []RemoteIovec, flags uint) (n int, err error) = SYS_PROCESS_VM_WRITEV
|
||||
|
||||
//sys PidfdOpen(pid int, flags int) (fd int, err error) = SYS_PIDFD_OPEN
|
||||
//sys PidfdGetfd(pidfd int, targetfd int, flags int) (fd int, err error) = SYS_PIDFD_GETFD
|
||||
|
||||
//sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
|
||||
//sys shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error)
|
||||
//sys shmdt(addr uintptr) (err error)
|
||||
//sys shmget(key int, size int, flag int) (id int, err error)
|
||||
|
||||
/*
|
||||
* Unimplemented
|
||||
*/
|
||||
@@ -2389,10 +2393,6 @@ type RemoteIovec struct {
|
||||
// SetRobustList
|
||||
// SetThreadArea
|
||||
// SetTidAddress
|
||||
// Shmat
|
||||
// Shmctl
|
||||
// Shmdt
|
||||
// Shmget
|
||||
// Sigaltstack
|
||||
// Swapoff
|
||||
// Swapon
|
||||
|
||||
-38
@@ -19,36 +19,8 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: int32(sec), Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
// 64-bit file system and 32-bit uid calls
|
||||
// (386 default is 32-bit file system and 16-bit uid).
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64_64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
||||
@@ -59,7 +31,6 @@ func Pipe2(p []int, flags int) (err error) {
|
||||
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
||||
//sysnb Getgid() (gid int) = SYS_GETGID32
|
||||
//sysnb Getuid() (uid int) = SYS_GETUID32
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
|
||||
@@ -381,12 +352,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
-48
@@ -7,8 +7,6 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -21,17 +19,6 @@ package unix
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb inotifyInit() (fd int, err error)
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
// First try inotify_init1, because Android's seccomp policy blocks the latter.
|
||||
fd, err = InotifyInit1(0)
|
||||
if err == ENOSYS {
|
||||
fd, err = inotifyInit()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
@@ -126,32 +113,6 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: usec}
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Rip }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Rip = pc }
|
||||
@@ -176,15 +137,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
|
||||
|
||||
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
|
||||
|
||||
-42
@@ -19,36 +19,6 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: int32(sec), Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
// Try pipe2 first for Android O, then try pipe for kernel 2.6.23.
|
||||
err = pipe2(&pp, 0)
|
||||
if err == ENOSYS {
|
||||
err = pipe(&pp)
|
||||
}
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||
newoffset, errno := seek(fd, offset, whence)
|
||||
if errno != 0 {
|
||||
@@ -76,8 +46,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||
|
||||
// 64-bit file system and 32-bit uid calls
|
||||
// (16-bit uid calls are not always supported in newer kernels)
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error) = SYS_FCHOWN32
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||
@@ -86,7 +54,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
|
||||
//sysnb Geteuid() (euid int) = SYS_GETEUID32
|
||||
//sysnb Getgid() (gid int) = SYS_GETGID32
|
||||
//sysnb Getuid() (uid int) = SYS_GETUID32
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error) = SYS_LCHOWN32
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
|
||||
@@ -260,15 +227,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys armSyncFileRange(fd int, flags int, off int64, n int64) (err error) = SYS_ARM_SYNC_FILE_RANGE
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) error {
|
||||
|
||||
-51
@@ -9,13 +9,6 @@ package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
if size <= 0 {
|
||||
return -1, EINVAL
|
||||
}
|
||||
return EpollCreate1(0)
|
||||
}
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -145,30 +138,6 @@ func utimes(path string, tv *[2]Timeval) (err error) {
|
||||
return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
// Getrlimit prefers the prlimit64 system call. See issue 38604.
|
||||
func Getrlimit(resource int, rlim *Rlimit) error {
|
||||
err := Prlimit(0, resource, nil, rlim)
|
||||
@@ -211,31 +180,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
// dup2 exists because func Dup3 in syscall_linux.go references
|
||||
// it in an unreachable path. dup2 isn't available on arm64.
|
||||
func dup2(oldfd int, newfd int) error
|
||||
|
||||
func Pause() error {
|
||||
_, err := ppoll(nil, 0, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout >= 0 {
|
||||
ts = new(Timespec)
|
||||
*ts = NsecToTimespec(int64(timeout) * 1e6)
|
||||
}
|
||||
if len(fds) == 0 {
|
||||
return ppoll(nil, 0, ts, nil)
|
||||
}
|
||||
return ppoll(&fds[0], len(fds), ts, nil)
|
||||
}
|
||||
|
||||
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
|
||||
|
||||
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
|
||||
|
||||
-39
@@ -8,8 +8,6 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -94,30 +92,6 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: usec}
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Ioperm(from int, num int, on int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
@@ -220,16 +194,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
-35
@@ -15,8 +15,6 @@ import (
|
||||
|
||||
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -60,7 +58,6 @@ func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr,
|
||||
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
|
||||
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
|
||||
@@ -113,29 +110,6 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: int32(sec), Usec: int32(usec)}
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe() (p1 int, p2 int, err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
p[0], p[1], err = pipe()
|
||||
return
|
||||
}
|
||||
|
||||
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
|
||||
|
||||
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
|
||||
@@ -232,12 +206,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint32(length)
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
-38
@@ -12,8 +12,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
|
||||
@@ -23,7 +21,6 @@ import (
|
||||
//sysnb Geteuid() (euid int)
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
@@ -218,41 +215,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint32(length)
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) error {
|
||||
|
||||
-38
@@ -8,8 +8,6 @@
|
||||
|
||||
package unix
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -22,7 +20,6 @@ package unix
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Ioperm(from int, num int, on int) (err error)
|
||||
//sys Iopl(level int) (err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
@@ -104,41 +101,6 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
|
||||
|
||||
func SyncFileRange(fd int, off int64, n int64, flags int) error {
|
||||
|
||||
-51
@@ -9,13 +9,6 @@ package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func EpollCreate(size int) (fd int, err error) {
|
||||
if size <= 0 {
|
||||
return -1, EINVAL
|
||||
}
|
||||
return EpollCreate1(0)
|
||||
}
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -144,30 +137,6 @@ func utimes(path string, tv *[2]Timeval) (err error) {
|
||||
return utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
|
||||
}
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func (r *PtraceRegs) PC() uint64 { return r.Pc }
|
||||
|
||||
func (r *PtraceRegs) SetPC(pc uint64) { r.Pc = pc }
|
||||
@@ -192,27 +161,11 @@ func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
func InotifyInit() (fd int, err error) {
|
||||
return InotifyInit1(0)
|
||||
}
|
||||
|
||||
func Pause() error {
|
||||
_, err := ppoll(nil, 0, nil, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
var ts *Timespec
|
||||
if timeout >= 0 {
|
||||
ts = new(Timespec)
|
||||
*ts = NsecToTimespec(int64(timeout) * 1e6)
|
||||
}
|
||||
if len(fds) == 0 {
|
||||
return ppoll(nil, 0, ts, nil)
|
||||
}
|
||||
return ppoll(&fds[0], len(fds), ts, nil)
|
||||
}
|
||||
|
||||
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
|
||||
return Renameat2(olddirfd, oldpath, newdirfd, newpath, 0)
|
||||
}
|
||||
@@ -229,7 +182,3 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||
}
|
||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||
}
|
||||
|
||||
// dup2 exists because func Dup3 in syscall_linux.go references
|
||||
// it in an unreachable path. dup2 isn't available on arm64.
|
||||
func dup2(oldfd int, newfd int) error
|
||||
-36
@@ -11,8 +11,6 @@ import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sysnb EpollCreate(size int) (fd int, err error)
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
@@ -25,7 +23,6 @@ import (
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||
//sys Pause() (err error)
|
||||
@@ -77,30 +74,6 @@ func setTimeval(sec, usec int64) Timeval {
|
||||
return Timeval{Sec: sec, Usec: usec}
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, 0) // pipe2 is the same as pipe when flags are set to 0.
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
func Ioperm(from int, num int, on int) (err error) {
|
||||
return ENOSYS
|
||||
}
|
||||
@@ -324,15 +297,6 @@ func Shutdown(s, how int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
|
||||
//sys kexecFileLoad(kernelFd int, initrdFd int, cmdlineLen int, cmdline string, flags int) (err error)
|
||||
|
||||
func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error {
|
||||
|
||||
-37
@@ -9,7 +9,6 @@ package unix
|
||||
|
||||
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
|
||||
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
|
||||
//sys dup2(oldfd int, newfd int) (err error)
|
||||
//sys Fchown(fd int, uid int, gid int) (err error)
|
||||
//sys Fstat(fd int, stat *Stat_t) (err error)
|
||||
//sys Fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
|
||||
@@ -20,7 +19,6 @@ package unix
|
||||
//sysnb Getgid() (gid int)
|
||||
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
|
||||
//sysnb Getuid() (uid int)
|
||||
//sysnb InotifyInit() (fd int, err error)
|
||||
//sys Lchown(path string, uid int, gid int) (err error)
|
||||
//sys Listen(s int, n int) (err error)
|
||||
//sys Lstat(path string, stat *Stat_t) (err error)
|
||||
@@ -119,38 +117,3 @@ func (cmsg *Cmsghdr) SetLen(length int) {
|
||||
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
|
||||
rsa.Service_name_len = uint64(length)
|
||||
}
|
||||
|
||||
//sysnb pipe(p *[2]_C_int) (err error)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe(&pp)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
|
||||
|
||||
func Pipe2(p []int, flags int) (err error) {
|
||||
if len(p) != 2 {
|
||||
return EINVAL
|
||||
}
|
||||
var pp [2]_C_int
|
||||
err = pipe2(&pp, flags)
|
||||
p[0] = int(pp[0])
|
||||
p[1] = int(pp[1])
|
||||
return
|
||||
}
|
||||
|
||||
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
|
||||
|
||||
func Poll(fds []PollFd, timeout int) (n int, err error) {
|
||||
if len(fds) == 0 {
|
||||
return poll(nil, 0, timeout)
|
||||
}
|
||||
return poll(&fds[0], len(fds), timeout)
|
||||
}
|
||||
+4
-12
@@ -92,9 +92,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet4, nil
|
||||
}
|
||||
|
||||
@@ -107,9 +105,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), SizeofSockaddrInet6, nil
|
||||
}
|
||||
|
||||
@@ -417,9 +413,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case AF_INET6:
|
||||
@@ -428,9 +422,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
|
||||
+4
-12
@@ -67,9 +67,7 @@ func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
|
||||
}
|
||||
|
||||
@@ -83,9 +81,7 @@ func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, _Socklen, error) {
|
||||
p[0] = byte(sa.Port >> 8)
|
||||
p[1] = byte(sa.Port)
|
||||
sa.raw.Scope_id = sa.ZoneId
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.raw.Addr[i] = sa.Addr[i]
|
||||
}
|
||||
sa.raw.Addr = sa.Addr
|
||||
return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
|
||||
}
|
||||
|
||||
@@ -144,9 +140,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
sa := new(SockaddrInet4)
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
|
||||
case AF_INET6:
|
||||
@@ -155,9 +149,7 @@ func anyToSockaddr(_ int, rsa *RawSockaddrAny) (Sockaddr, error) {
|
||||
p := (*[2]byte)(unsafe.Pointer(&pp.Port))
|
||||
sa.Port = int(p[0])<<8 + int(p[1])
|
||||
sa.ZoneId = pp.Scope_id
|
||||
for i := 0; i < len(sa.Addr); i++ {
|
||||
sa.Addr[i] = pp.Addr[i]
|
||||
}
|
||||
sa.Addr = pp.Addr
|
||||
return sa, nil
|
||||
}
|
||||
return nil, EAFNOSUPPORT
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package unix
|
||||
|
||||
import "runtime"
|
||||
|
||||
// SysvShmCtl performs control operations on the shared memory segment
|
||||
// specified by id.
|
||||
func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) {
|
||||
if runtime.GOARCH == "arm" ||
|
||||
runtime.GOARCH == "mips64" || runtime.GOARCH == "mips64le" {
|
||||
cmd |= ipc_64
|
||||
}
|
||||
|
||||
return shmctl(id, cmd, desc)
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build (darwin && !ios) || linux
|
||||
// +build darwin,!ios linux
|
||||
|
||||
package unix
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/internal/unsafeheader"
|
||||
)
|
||||
|
||||
// SysvShmAttach attaches the Sysv shared memory segment associated with the
|
||||
// shared memory identifier id.
|
||||
func SysvShmAttach(id int, addr uintptr, flag int) ([]byte, error) {
|
||||
addr, errno := shmat(id, addr, flag)
|
||||
if errno != nil {
|
||||
return nil, errno
|
||||
}
|
||||
|
||||
// Retrieve the size of the shared memory to enable slice creation
|
||||
var info SysvShmDesc
|
||||
|
||||
_, err := SysvShmCtl(id, IPC_STAT, &info)
|
||||
if err != nil {
|
||||
// release the shared memory if we can't find the size
|
||||
|
||||
// ignoring error from shmdt as there's nothing sensible to return here
|
||||
shmdt(addr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Use unsafe to convert addr into a []byte.
|
||||
// TODO: convert to unsafe.Slice once we can assume Go 1.17
|
||||
var b []byte
|
||||
hdr := (*unsafeheader.Slice)(unsafe.Pointer(&b))
|
||||
hdr.Data = unsafe.Pointer(addr)
|
||||
hdr.Cap = int(info.Segsz)
|
||||
hdr.Len = int(info.Segsz)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// SysvShmDetach unmaps the shared memory slice returned from SysvShmAttach.
|
||||
//
|
||||
// It is not safe to use the slice after calling this function.
|
||||
func SysvShmDetach(data []byte) error {
|
||||
if len(data) == 0 {
|
||||
return EINVAL
|
||||
}
|
||||
|
||||
return shmdt(uintptr(unsafe.Pointer(&data[0])))
|
||||
}
|
||||
|
||||
// SysvShmGet returns the Sysv shared memory identifier associated with key.
|
||||
// If the IPC_CREAT flag is specified a new segment is created.
|
||||
func SysvShmGet(key, size, flag int) (id int, err error) {
|
||||
return shmget(key, size, flag)
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build darwin && !ios
|
||||
// +build darwin,!ios
|
||||
|
||||
package unix
|
||||
|
||||
// SysvShmCtl performs control operations on the shared memory segment
|
||||
// specified by id.
|
||||
func SysvShmCtl(id, cmd int, desc *SysvShmDesc) (result int, err error) {
|
||||
return shmctl(id, cmd, desc)
|
||||
}
|
||||
+1576
-1550
File diff suppressed because it is too large.
Load diff
+1576
-1550
File diff suppressed because it is too large.
Load diff
+66
-2
@@ -1,4 +1,4 @@
|
||||
// Code generated by mkmerge.go; DO NOT EDIT.
|
||||
// Code generated by mkmerge; DO NOT EDIT.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
@@ -116,6 +116,7 @@ const (
|
||||
ARPHRD_LAPB = 0x204
|
||||
ARPHRD_LOCALTLK = 0x305
|
||||
ARPHRD_LOOPBACK = 0x304
|
||||
ARPHRD_MCTP = 0x122
|
||||
ARPHRD_METRICOM = 0x17
|
||||
ARPHRD_NETLINK = 0x338
|
||||
ARPHRD_NETROM = 0x0
|
||||
@@ -231,6 +232,8 @@ const (
|
||||
BPF_PSEUDO_FUNC = 0x4
|
||||
BPF_PSEUDO_KFUNC_CALL = 0x2
|
||||
BPF_PSEUDO_MAP_FD = 0x1
|
||||
BPF_PSEUDO_MAP_IDX = 0x5
|
||||
BPF_PSEUDO_MAP_IDX_VALUE = 0x6
|
||||
BPF_PSEUDO_MAP_VALUE = 0x2
|
||||
BPF_RET = 0x6
|
||||
BPF_RSH = 0x70
|
||||
@@ -470,6 +473,7 @@ const (
|
||||
DM_DEV_WAIT = 0xc138fd08
|
||||
DM_DIR = "mapper"
|
||||
DM_GET_TARGET_VERSION = 0xc138fd11
|
||||
DM_IMA_MEASUREMENT_FLAG = 0x80000
|
||||
DM_INACTIVE_PRESENT_FLAG = 0x40
|
||||
DM_INTERNAL_SUSPEND_FLAG = 0x40000
|
||||
DM_IOCTL = 0xfd
|
||||
@@ -714,6 +718,7 @@ const (
|
||||
ETH_P_LOOPBACK = 0x9000
|
||||
ETH_P_MACSEC = 0x88e5
|
||||
ETH_P_MAP = 0xf9
|
||||
ETH_P_MCTP = 0xfa
|
||||
ETH_P_MOBITEX = 0x15
|
||||
ETH_P_MPLS_MC = 0x8848
|
||||
ETH_P_MPLS_UC = 0x8847
|
||||
@@ -749,6 +754,21 @@ const (
|
||||
ETH_P_WCCP = 0x883e
|
||||
ETH_P_X25 = 0x805
|
||||
ETH_P_XDSA = 0xf8
|
||||
EV_ABS = 0x3
|
||||
EV_CNT = 0x20
|
||||
EV_FF = 0x15
|
||||
EV_FF_STATUS = 0x17
|
||||
EV_KEY = 0x1
|
||||
EV_LED = 0x11
|
||||
EV_MAX = 0x1f
|
||||
EV_MSC = 0x4
|
||||
EV_PWR = 0x16
|
||||
EV_REL = 0x2
|
||||
EV_REP = 0x14
|
||||
EV_SND = 0x12
|
||||
EV_SW = 0x5
|
||||
EV_SYN = 0x0
|
||||
EV_VERSION = 0x10001
|
||||
EXABYTE_ENABLE_NEST = 0xf0
|
||||
EXT2_SUPER_MAGIC = 0xef53
|
||||
EXT3_SUPER_MAGIC = 0xef53
|
||||
@@ -787,9 +807,11 @@ const (
|
||||
FAN_DELETE_SELF = 0x400
|
||||
FAN_DENY = 0x2
|
||||
FAN_ENABLE_AUDIT = 0x40
|
||||
FAN_EPIDFD = -0x2
|
||||
FAN_EVENT_INFO_TYPE_DFID = 0x3
|
||||
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
|
||||
FAN_EVENT_INFO_TYPE_FID = 0x1
|
||||
FAN_EVENT_INFO_TYPE_PIDFD = 0x4
|
||||
FAN_EVENT_METADATA_LEN = 0x18
|
||||
FAN_EVENT_ON_CHILD = 0x8000000
|
||||
FAN_MARK_ADD = 0x1
|
||||
@@ -809,6 +831,7 @@ const (
|
||||
FAN_MOVE_SELF = 0x800
|
||||
FAN_NOFD = -0x1
|
||||
FAN_NONBLOCK = 0x2
|
||||
FAN_NOPIDFD = -0x1
|
||||
FAN_ONDIR = 0x40000000
|
||||
FAN_OPEN = 0x20
|
||||
FAN_OPEN_EXEC = 0x1000
|
||||
@@ -819,6 +842,7 @@ const (
|
||||
FAN_REPORT_DIR_FID = 0x400
|
||||
FAN_REPORT_FID = 0x200
|
||||
FAN_REPORT_NAME = 0x800
|
||||
FAN_REPORT_PIDFD = 0x80
|
||||
FAN_REPORT_TID = 0x100
|
||||
FAN_UNLIMITED_MARKS = 0x20
|
||||
FAN_UNLIMITED_QUEUE = 0x10
|
||||
@@ -1331,6 +1355,20 @@ const (
|
||||
KEY_SPEC_THREAD_KEYRING = -0x1
|
||||
KEY_SPEC_USER_KEYRING = -0x4
|
||||
KEY_SPEC_USER_SESSION_KEYRING = -0x5
|
||||
LANDLOCK_ACCESS_FS_EXECUTE = 0x1
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK = 0x800
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR = 0x40
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR = 0x80
|
||||
LANDLOCK_ACCESS_FS_MAKE_FIFO = 0x400
|
||||
LANDLOCK_ACCESS_FS_MAKE_REG = 0x100
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK = 0x200
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM = 0x1000
|
||||
LANDLOCK_ACCESS_FS_READ_DIR = 0x8
|
||||
LANDLOCK_ACCESS_FS_READ_FILE = 0x4
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR = 0x10
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE = 0x20
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE = 0x2
|
||||
LANDLOCK_CREATE_RULESET_VERSION = 0x1
|
||||
LINUX_REBOOT_CMD_CAD_OFF = 0x0
|
||||
LINUX_REBOOT_CMD_CAD_ON = 0x89abcdef
|
||||
LINUX_REBOOT_CMD_HALT = 0xcdef0123
|
||||
@@ -1381,6 +1419,8 @@ const (
|
||||
MADV_NOHUGEPAGE = 0xf
|
||||
MADV_NORMAL = 0x0
|
||||
MADV_PAGEOUT = 0x15
|
||||
MADV_POPULATE_READ = 0x16
|
||||
MADV_POPULATE_WRITE = 0x17
|
||||
MADV_RANDOM = 0x1
|
||||
MADV_REMOVE = 0x9
|
||||
MADV_SEQUENTIAL = 0x2
|
||||
@@ -1436,6 +1476,18 @@ const (
|
||||
MNT_FORCE = 0x1
|
||||
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
|
||||
MODULE_INIT_IGNORE_VERMAGIC = 0x2
|
||||
MOUNT_ATTR_IDMAP = 0x100000
|
||||
MOUNT_ATTR_NOATIME = 0x10
|
||||
MOUNT_ATTR_NODEV = 0x4
|
||||
MOUNT_ATTR_NODIRATIME = 0x80
|
||||
MOUNT_ATTR_NOEXEC = 0x8
|
||||
MOUNT_ATTR_NOSUID = 0x2
|
||||
MOUNT_ATTR_NOSYMFOLLOW = 0x200000
|
||||
MOUNT_ATTR_RDONLY = 0x1
|
||||
MOUNT_ATTR_RELATIME = 0x0
|
||||
MOUNT_ATTR_SIZE_VER0 = 0x20
|
||||
MOUNT_ATTR_STRICTATIME = 0x20
|
||||
MOUNT_ATTR__ATIME = 0x70
|
||||
MSDOS_SUPER_MAGIC = 0x4d44
|
||||
MSG_BATCH = 0x40000
|
||||
MSG_CMSG_CLOEXEC = 0x40000000
|
||||
@@ -1635,11 +1687,12 @@ const (
|
||||
NFNL_MSG_BATCH_END = 0x11
|
||||
NFNL_NFA_NEST = 0x8000
|
||||
NFNL_SUBSYS_ACCT = 0x7
|
||||
NFNL_SUBSYS_COUNT = 0xc
|
||||
NFNL_SUBSYS_COUNT = 0xd
|
||||
NFNL_SUBSYS_CTHELPER = 0x9
|
||||
NFNL_SUBSYS_CTNETLINK = 0x1
|
||||
NFNL_SUBSYS_CTNETLINK_EXP = 0x2
|
||||
NFNL_SUBSYS_CTNETLINK_TIMEOUT = 0x8
|
||||
NFNL_SUBSYS_HOOK = 0xc
|
||||
NFNL_SUBSYS_IPSET = 0x6
|
||||
NFNL_SUBSYS_NFTABLES = 0xa
|
||||
NFNL_SUBSYS_NFT_COMPAT = 0xb
|
||||
@@ -1929,6 +1982,12 @@ const (
|
||||
PR_PAC_GET_ENABLED_KEYS = 0x3d
|
||||
PR_PAC_RESET_KEYS = 0x36
|
||||
PR_PAC_SET_ENABLED_KEYS = 0x3c
|
||||
PR_SCHED_CORE = 0x3e
|
||||
PR_SCHED_CORE_CREATE = 0x1
|
||||
PR_SCHED_CORE_GET = 0x0
|
||||
PR_SCHED_CORE_MAX = 0x4
|
||||
PR_SCHED_CORE_SHARE_FROM = 0x3
|
||||
PR_SCHED_CORE_SHARE_TO = 0x2
|
||||
PR_SET_CHILD_SUBREAPER = 0x24
|
||||
PR_SET_DUMPABLE = 0x4
|
||||
PR_SET_ENDIAN = 0x14
|
||||
@@ -1972,6 +2031,7 @@ const (
|
||||
PR_SPEC_ENABLE = 0x2
|
||||
PR_SPEC_FORCE_DISABLE = 0x8
|
||||
PR_SPEC_INDIRECT_BRANCH = 0x1
|
||||
PR_SPEC_L1D_FLUSH = 0x2
|
||||
PR_SPEC_NOT_AFFECTED = 0x0
|
||||
PR_SPEC_PRCTL = 0x1
|
||||
PR_SPEC_STORE_BYPASS = 0x0
|
||||
@@ -2295,6 +2355,7 @@ const (
|
||||
SECCOMP_MODE_DISABLED = 0x0
|
||||
SECCOMP_MODE_FILTER = 0x2
|
||||
SECCOMP_MODE_STRICT = 0x1
|
||||
SECRETMEM_MAGIC = 0x5345434d
|
||||
SECURITYFS_MAGIC = 0x73636673
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
@@ -2406,12 +2467,15 @@ const (
|
||||
SMART_WRITE_THRESHOLDS = 0xd7
|
||||
SMB_SUPER_MAGIC = 0x517b
|
||||
SOCKFS_MAGIC = 0x534f434b
|
||||
SOCK_BUF_LOCK_MASK = 0x3
|
||||
SOCK_DCCP = 0x6
|
||||
SOCK_IOC_TYPE = 0x89
|
||||
SOCK_PACKET = 0xa
|
||||
SOCK_RAW = 0x3
|
||||
SOCK_RCVBUF_LOCK = 0x2
|
||||
SOCK_RDM = 0x4
|
||||
SOCK_SEQPACKET = 0x5
|
||||
SOCK_SNDBUF_LOCK = 0x1
|
||||
SOL_AAL = 0x109
|
||||
SOL_ALG = 0x117
|
||||
SOL_ATM = 0x108
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build 386,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -293,6 +293,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -309,6 +310,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build amd64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -294,6 +294,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -310,6 +311,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build arm,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -300,6 +300,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -316,6 +317,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build arm64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -290,6 +290,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -306,6 +307,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build mips,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -293,6 +293,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x20
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -309,6 +310,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0x100
|
||||
SO_PASSCRED = 0x11
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build mips64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -293,6 +293,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x20
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -309,6 +310,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0x100
|
||||
SO_PASSCRED = 0x11
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build mips64le,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -293,6 +293,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x20
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -309,6 +310,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0x100
|
||||
SO_PASSCRED = 0x11
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build mipsle,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -293,6 +293,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x20
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -309,6 +310,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0x100
|
||||
SO_PASSCRED = 0x11
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build ppc,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -348,6 +348,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -364,6 +365,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x14
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build ppc64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -352,6 +352,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -368,6 +369,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x14
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build ppc64le,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -352,6 +352,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -368,6 +369,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x14
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build riscv64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -281,6 +281,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -297,6 +298,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build s390x,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -356,6 +356,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x30
|
||||
SO_BROADCAST = 0x6
|
||||
SO_BSDCOMPAT = 0xe
|
||||
SO_BUF_LOCK = 0x48
|
||||
SO_BUSY_POLL = 0x2e
|
||||
SO_BUSY_POLL_BUDGET = 0x46
|
||||
SO_CNX_ADVICE = 0x35
|
||||
@@ -372,6 +373,7 @@ const (
|
||||
SO_MARK = 0x24
|
||||
SO_MAX_PACING_RATE = 0x2f
|
||||
SO_MEMINFO = 0x37
|
||||
SO_NETNS_COOKIE = 0x47
|
||||
SO_NOFCS = 0x2b
|
||||
SO_OOBINLINE = 0xa
|
||||
SO_PASSCRED = 0x10
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// +build sparc64,linux
|
||||
|
||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/_const.go
|
||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
||||
|
||||
package unix
|
||||
|
||||
@@ -347,6 +347,7 @@ const (
|
||||
SO_BPF_EXTENSIONS = 0x32
|
||||
SO_BROADCAST = 0x20
|
||||
SO_BSDCOMPAT = 0x400
|
||||
SO_BUF_LOCK = 0x51
|
||||
SO_BUSY_POLL = 0x30
|
||||
SO_BUSY_POLL_BUDGET = 0x49
|
||||
SO_CNX_ADVICE = 0x37
|
||||
@@ -363,6 +364,7 @@ const (
|
||||
SO_MARK = 0x22
|
||||
SO_MAX_PACING_RATE = 0x31
|
||||
SO_MEMINFO = 0x39
|
||||
SO_NETNS_COOKIE = 0x50
|
||||
SO_NOFCS = 0x27
|
||||
SO_OOBINLINE = 0x100
|
||||
SO_PASSCRED = 0x2
|
||||
|
||||
+11
-11
@@ -17,6 +17,7 @@ int getdirent(int, uintptr_t, size_t);
|
||||
int wait4(int, uintptr_t, int, uintptr_t);
|
||||
int ioctl(int, int, uintptr_t);
|
||||
int fcntl(uintptr_t, int, uintptr_t);
|
||||
int fsync_range(int, int, long long, long long);
|
||||
int acct(uintptr_t);
|
||||
int chdir(uintptr_t);
|
||||
int chroot(uintptr_t);
|
||||
@@ -29,7 +30,6 @@ int fchmod(int, unsigned int);
|
||||
int fchmodat(int, uintptr_t, unsigned int, int);
|
||||
int fchownat(int, uintptr_t, int, int, int);
|
||||
int fdatasync(int);
|
||||
int fsync(int);
|
||||
int getpgid(int);
|
||||
int getpgrp();
|
||||
int getpid();
|
||||
@@ -255,6 +255,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func fsyncRange(fd int, how int, start int64, length int64) (err error) {
|
||||
r0, er := C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length))
|
||||
if r0 == -1 && er != nil {
|
||||
err = er
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Acct(path string) (err error) {
|
||||
_p0 := uintptr(unsafe.Pointer(C.CString(path)))
|
||||
r0, er := C.acct(C.uintptr_t(_p0))
|
||||
@@ -379,16 +389,6 @@ func Fdatasync(fd int) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Fsync(fd int) (err error) {
|
||||
r0, er := C.fsync(C.int(fd))
|
||||
if r0 == -1 && er != nil {
|
||||
err = er
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Getpgid(pid int) (pgid int, err error) {
|
||||
r0, er := C.getpgid(C.int(pid))
|
||||
pgid = int(r0)
|
||||
|
||||
+10
-10
@@ -135,6 +135,16 @@ func fcntl(fd int, cmd int, arg int) (val int, err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func fsyncRange(fd int, how int, start int64, length int64) (err error) {
|
||||
_, e1 := callfsync_range(fd, how, start, length)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Acct(path string) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = BytePtrFromString(path)
|
||||
@@ -283,16 +293,6 @@ func Fdatasync(fd int) (err error) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Fsync(fd int) (err error) {
|
||||
_, e1 := callfsync(fd)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Getpgid(pid int) (pgid int, err error) {
|
||||
r0, e1 := callgetpgid(pid)
|
||||
pgid = int(r0)
|
||||
|
||||
+10
-10
@@ -18,6 +18,7 @@ import (
|
||||
//go:cgo_import_dynamic libc_wait4 wait4 "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_fcntl fcntl "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_fsync_range fsync_range "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_acct acct "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_chdir chdir "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_chroot chroot "libc.a/shr_64.o"
|
||||
@@ -30,7 +31,6 @@ import (
|
||||
//go:cgo_import_dynamic libc_fchmodat fchmodat "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_fchownat fchownat "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_fdatasync fdatasync "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_fsync fsync "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_getpgid getpgid "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_getpgrp getpgrp "libc.a/shr_64.o"
|
||||
//go:cgo_import_dynamic libc_getpid getpid "libc.a/shr_64.o"
|
||||
@@ -136,6 +136,7 @@ import (
|
||||
//go:linkname libc_wait4 libc_wait4
|
||||
//go:linkname libc_ioctl libc_ioctl
|
||||
//go:linkname libc_fcntl libc_fcntl
|
||||
//go:linkname libc_fsync_range libc_fsync_range
|
||||
//go:linkname libc_acct libc_acct
|
||||
//go:linkname libc_chdir libc_chdir
|
||||
//go:linkname libc_chroot libc_chroot
|
||||
@@ -148,7 +149,6 @@ import (
|
||||
//go:linkname libc_fchmodat libc_fchmodat
|
||||
//go:linkname libc_fchownat libc_fchownat
|
||||
//go:linkname libc_fdatasync libc_fdatasync
|
||||
//go:linkname libc_fsync libc_fsync
|
||||
//go:linkname libc_getpgid libc_getpgid
|
||||
//go:linkname libc_getpgrp libc_getpgrp
|
||||
//go:linkname libc_getpid libc_getpid
|
||||
@@ -257,6 +257,7 @@ var (
|
||||
libc_wait4,
|
||||
libc_ioctl,
|
||||
libc_fcntl,
|
||||
libc_fsync_range,
|
||||
libc_acct,
|
||||
libc_chdir,
|
||||
libc_chroot,
|
||||
@@ -269,7 +270,6 @@ var (
|
||||
libc_fchmodat,
|
||||
libc_fchownat,
|
||||
libc_fdatasync,
|
||||
libc_fsync,
|
||||
libc_getpgid,
|
||||
libc_getpgrp,
|
||||
libc_getpid,
|
||||
@@ -430,6 +430,13 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync_range)), 4, uintptr(fd), uintptr(how), uintptr(start), uintptr(length), 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_acct)), 1, _p0, 0, 0, 0, 0, 0)
|
||||
return
|
||||
@@ -514,13 +521,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callfsync(fd int) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_fsync)), 1, uintptr(fd), 0, 0, 0, 0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callgetpgid(pid int) (r1 uintptr, e1 Errno) {
|
||||
r1, _, e1 = rawSyscall6(uintptr(unsafe.Pointer(&libc_getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0)
|
||||
return
|
||||
|
||||
+9
-9
@@ -16,6 +16,7 @@ int getdirent(int, uintptr_t, size_t);
|
||||
int wait4(int, uintptr_t, int, uintptr_t);
|
||||
int ioctl(int, int, uintptr_t);
|
||||
int fcntl(uintptr_t, int, uintptr_t);
|
||||
int fsync_range(int, int, long long, long long);
|
||||
int acct(uintptr_t);
|
||||
int chdir(uintptr_t);
|
||||
int chroot(uintptr_t);
|
||||
@@ -28,7 +29,6 @@ int fchmod(int, unsigned int);
|
||||
int fchmodat(int, uintptr_t, unsigned int, int);
|
||||
int fchownat(int, uintptr_t, int, int, int);
|
||||
int fdatasync(int);
|
||||
int fsync(int);
|
||||
int getpgid(int);
|
||||
int getpgrp();
|
||||
int getpid();
|
||||
@@ -199,6 +199,14 @@ func callfcntl(fd uintptr, cmd int, arg uintptr) (r1 uintptr, e1 Errno) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callfsync_range(fd int, how int, start int64, length int64) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.fsync_range(C.int(fd), C.int(how), C.longlong(start), C.longlong(length)))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callacct(_p0 uintptr) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.acct(C.uintptr_t(_p0)))
|
||||
e1 = syscall.GetErrno()
|
||||
@@ -295,14 +303,6 @@ func callfdatasync(fd int) (r1 uintptr, e1 Errno) {
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callfsync(fd int) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.fsync(C.int(fd)))
|
||||
e1 = syscall.GetErrno()
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func callgetpgid(pid int) (r1 uintptr, e1 Errno) {
|
||||
r1 = uintptr(C.getpgid(C.int(pid)))
|
||||
e1 = syscall.GetErrno()
|
||||
|
||||
+59
@@ -734,6 +734,65 @@ var libc_sendfile_trampoline_addr uintptr
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func shmat(id int, addr uintptr, flag int) (ret uintptr, err error) {
|
||||
r0, _, e1 := syscall_syscall(libc_shmat_trampoline_addr, uintptr(id), uintptr(addr), uintptr(flag))
|
||||
ret = uintptr(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var libc_shmat_trampoline_addr uintptr
|
||||
|
||||
//go:cgo_import_dynamic libc_shmat shmat "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func shmctl(id int, cmd int, buf *SysvShmDesc) (result int, err error) {
|
||||
r0, _, e1 := syscall_syscall(libc_shmctl_trampoline_addr, uintptr(id), uintptr(cmd), uintptr(unsafe.Pointer(buf)))
|
||||
result = int(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var libc_shmctl_trampoline_addr uintptr
|
||||
|
||||
//go:cgo_import_dynamic libc_shmctl shmctl "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func shmdt(addr uintptr) (err error) {
|
||||
_, _, e1 := syscall_syscall(libc_shmdt_trampoline_addr, uintptr(addr), 0, 0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var libc_shmdt_trampoline_addr uintptr
|
||||
|
||||
//go:cgo_import_dynamic libc_shmdt shmdt "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func shmget(key int, size int, flag int) (id int, err error) {
|
||||
r0, _, e1 := syscall_syscall(libc_shmget_trampoline_addr, uintptr(key), uintptr(size), uintptr(flag))
|
||||
id = int(r0)
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var libc_shmget_trampoline_addr uintptr
|
||||
|
||||
//go:cgo_import_dynamic libc_shmget shmget "/usr/lib/libSystem.B.dylib"
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Access(path string, mode uint32) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = BytePtrFromString(path)
|
||||
|
||||
Loaded 100 of 182 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user