diff --git a/go.mod b/go.mod index 37f8a2da..272652a9 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,14 @@ require ( ) require ( + github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect + github.com/99designs/keyring v1.2.2 // indirect + github.com/danieljoos/wincred v1.1.2 // indirect + github.com/dvsekhvalnov/jose2go v1.7.0 // indirect github.com/geoffgarside/ber v1.1.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/mtibben/percent v0.2.1 // indirect golang.org/x/crypto v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index f3ff090c..cade7d54 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,39 @@ +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= +github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= +github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= +github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= +github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= +github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI= github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE= github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4= github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.16.7 h1:fgztTxllw7+GvSj6KZ9m41g0M8n81/NP4zjPr6IrBCI= github.com/open-amt-cloud-toolkit/go-wsman-messages/v2 v2.16.7/go.mod h1:ZFZRyYEYWs2ngCuwzK+n+vc0ga1Hh4BRJYBiwXxDTD0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -22,6 +41,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -32,14 +52,16 @@ golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOM golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/flags/activate.go b/internal/flags/activate.go index 4abb4332..5aeca873 100644 --- a/internal/flags/activate.go +++ b/internal/flags/activate.go @@ -29,6 +29,8 @@ func (f *Flags) handleActivateCommand() error { f.amtActivateCommand.BoolVar(&f.SkipIPRenew, "skipIPRenew", false, "skip DHCP renewal of the IP address if AMT becomes enabled") // for local activation in ACM mode need a few more items f.amtActivateCommand.StringVar(&f.configContent, "config", "", "specify a config file or smb: file share URL") + f.amtActivateCommand.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + f.amtActivateCommand.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") f.amtActivateCommand.StringVar(&f.LocalConfig.ACMSettings.AMTPassword, "amtPassword", f.lookupEnvOrString("AMT_PASSWORD", ""), "amt password") f.amtActivateCommand.StringVar(&f.LocalConfig.ACMSettings.ProvisioningCert, "provisioningCert", f.lookupEnvOrString("PROVISIONING_CERT", ""), "provisioning certificate") f.amtActivateCommand.StringVar(&f.LocalConfig.ACMSettings.ProvisioningCertPwd, "provisioningCertPwd", f.lookupEnvOrString("PROVISIONING_CERT_PASSWORD", ""), "provisioning certificate password") @@ -78,47 +80,108 @@ func (f *Flags) handleActivateCommand() error { fmt.Println("Warning: Overriding UUID prevents device from connecting to MPS") } } else { - if !f.UseCCM && !f.UseACM || f.UseCCM && f.UseACM { - fmt.Println("must specify -ccm or -acm, but not both") - return utils.InvalidParameterCombination - } - - err := f.handleLocalConfig() - if err != nil { - return utils.FailedReadingConfiguration - } + if f.configContentV2 != "" { + err := f.handleLocalConfigV2() + if err != nil { + return utils.FailedReadingConfiguration + } - // Gets optimized in rpc-go version 3 - if f.LocalConfig.CCMSettings.AMTPassword != "" { - f.LocalConfig.Password = f.LocalConfig.CCMSettings.AMTPassword - } + err = f.ValidateConfigV2() + if err != nil { + return err + } - if (f.LocalConfig.ACMSettings.AMTPassword == "" || f.LocalConfig.CCMSettings.AMTPassword == "") && f.Password == "" { - if rc := f.ReadNewPasswordTo(&f.Password, "New AMT Password"); rc != nil { - return rc + } else { + err := f.handleLocalConfigV1() + if err != nil { + return err } } + } + return nil +} + +func (f *Flags) handleLocalConfigV1() error { + if !f.UseCCM && !f.UseACM || f.UseCCM && f.UseACM { + fmt.Println("must specify -ccm or -acm, but not both") + return utils.InvalidParameterCombination + } + + err := f.handleLocalConfig() + if err != nil { + return utils.FailedReadingConfiguration + } + + // Gets optimized in rpc-go version 3 + if f.LocalConfig.CCMSettings.AMTPassword != "" { + f.LocalConfig.Password = f.LocalConfig.CCMSettings.AMTPassword + } - if f.Password != "" { - f.LocalConfig.ACMSettings.AMTPassword = f.Password - f.LocalConfig.Password = f.Password + if (f.LocalConfig.ACMSettings.AMTPassword == "" || f.LocalConfig.CCMSettings.AMTPassword == "") && f.Password == "" { + if rc := f.ReadNewPasswordTo(&f.Password, "New AMT Password"); rc != nil { + return rc } + } + + if f.Password != "" { + f.LocalConfig.ACMSettings.AMTPassword = f.Password + f.LocalConfig.Password = f.Password + } - if f.UseACM { - v := reflect.ValueOf(f.LocalConfig.ACMSettings) - for i := 0; i < v.NumField(); i++ { - if v.Field(i).Interface() == "" { // not checking 0 since authenticantProtocol can and needs to be 0 for EAP-TLS - log.Error("Missing value for field: ", v.Type().Field(i).Name) - return utils.IncorrectCommandLineParameters - } + if f.UseACM { + v := reflect.ValueOf(f.LocalConfig.ACMSettings) + for i := 0; i < v.NumField(); i++ { + if v.Field(i).Interface() == "" { // not checking 0 since authenticantProtocol can and needs to be 0 for EAP-TLS + log.Error("Missing value for field: ", v.Type().Field(i).Name) + return utils.IncorrectCommandLineParameters } } + } - if f.UUID != "" { - fmt.Println("-uuid cannot be use in local activation") - f.amtActivateCommand.Usage() - return utils.InvalidParameterCombination + if f.UUID != "" { + fmt.Println("-uuid cannot be use in local activation") + f.amtActivateCommand.Usage() + return utils.InvalidParameterCombination + } + + return nil +} + +func (f *Flags) ValidateConfigV2() error { + // Check if the Control Mode is set + switch f.LocalConfigV2.Configuration.AMTSpecific.ControlMode { + case "acmactivate": + f.UseACM = true + case "ccmactivate": + f.UseCCM = true + default: + log.Error("Invalid Control Mode") + return utils.IncorrectCommandLineParameters //ToDo: Add a new error type + } + + // Check if the AMT Password is set + if f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword == "" { + log.Warn("AMT Password is not set") + if rc := f.ReadNewPasswordTo(&f.Password, "New AMT Password"); rc != nil { + return rc } } + f.LocalConfig.ACMSettings.AMTPassword = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + f.LocalConfig.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + + // Check if the Provisioning Certificate is set + if f.LocalConfigV2.Configuration.AMTSpecific.ProvisioningCert == "" { + log.Error("Provisioning Certificate is not set") + return utils.IncorrectCommandLineParameters //ToDo: Add a new error type + } + f.LocalConfig.ACMSettings.ProvisioningCert = f.LocalConfigV2.Configuration.AMTSpecific.ProvisioningCert + + // Check if the Provisioning Certificate Password is set + if f.LocalConfigV2.Configuration.AMTSpecific.ProvisioningCertPwd == "" { + log.Error("Provisioning Certificate Password is not set") + return utils.IncorrectCommandLineParameters //ToDo: Add a new error type + } + f.LocalConfig.ACMSettings.ProvisioningCertPwd = f.LocalConfigV2.Configuration.AMTSpecific.ProvisioningCertPwd + return nil } diff --git a/internal/flags/configure.go b/internal/flags/configure.go index 6e16b10c..d0ab22c7 100644 --- a/internal/flags/configure.go +++ b/internal/flags/configure.go @@ -30,6 +30,7 @@ const ( TLSModeServerAndNonTLS TLSModeMutual TLSModeMutualAndNonTLS + TLSModeDisabled ) func (m TLSMode) String() string { @@ -42,13 +43,15 @@ func (m TLSMode) String() string { return "Mutual" case TLSModeMutualAndNonTLS: return "MutualAndNonTLS" + case TLSModeDisabled: + return "None" default: return "Unknown" } } func TLSModesToString() string { - return fmt.Sprintf("%s, %s, %s, %s", TLSModeServer, TLSModeServerAndNonTLS, TLSModeMutual, TLSModeMutualAndNonTLS) + return fmt.Sprintf("%s, %s, %s, %s, %s", TLSModeServer, TLSModeServerAndNonTLS, TLSModeMutual, TLSModeMutualAndNonTLS, TLSModeDisabled) } func ParseTLSMode(s string) (TLSMode, error) { @@ -63,6 +66,8 @@ func ParseTLSMode(s string) (TLSMode, error) { m = TLSModeMutual case "MutualAndNonTLS": m = TLSModeMutualAndNonTLS + case "None": + m = TLSModeDisabled default: // flags error handling already shows appropriate message err = errors.New("") @@ -78,6 +83,28 @@ type ConfigTLSInfo struct { EAPassword string } +// authenticationMethodMap now maps strings directly to integer values +var authenticationMethod = map[string]wifi.AuthenticationMethod{ + "Other": wifi.AuthenticationMethodOther, + "OpenSystem": wifi.AuthenticationMethodOpenSystem, + "SharedKey": wifi.AuthenticationMethodSharedKey, + "WPAPSK": wifi.AuthenticationMethodWPAPSK, + "WPAIEEE8021x": wifi.AuthenticationMethodWPAIEEE8021x, + "WPA2PSK": wifi.AuthenticationMethodWPA2PSK, + "WPA2IEEE8021x": wifi.AuthenticationMethodWPA2IEEE8021x, + "WPA3SAE": wifi.AuthenticationMethodWPA3SAE, + "WPA3OWE": wifi.AuthenticationMethodWPA3OWE, +} + +// encryptionMethod Map now maps strings directly to integer values +var encryptionMethod = map[string]wifi.EncryptionMethod{ + "Other": wifi.EncryptionMethod_Other, + "WEP": wifi.EncryptionMethod_WEP, + "TKIP": wifi.EncryptionMethod_TKIP, + "CCMP": wifi.EncryptionMethod_CCMP, + "None": wifi.EncryptionMethod_None, +} + func (f *Flags) printConfigurationUsage() string { baseCommand := fmt.Sprintf("%s %s", filepath.Base(os.Args[0]), utils.CommandConfigure) usage := "\nRemote Provisioning Client (RPC) - used for activation, deactivation, maintenance and status of AMT\n\n" @@ -145,21 +172,23 @@ func (f *Flags) handleConfigureCommand() error { } f.Local = true - if f.Password == "" { - if f.LocalConfig.Password != "" { - f.Password = f.LocalConfig.Password + if f.SubCommand != utils.SubCommandSetAMTFeatures { + if f.Password == "" { + if f.LocalConfig.Password != "" { + f.Password = f.LocalConfig.Password + } else { + if err = f.ReadPasswordFromUser(); err != nil { + return utils.MissingOrIncorrectPassword + } + f.LocalConfig.Password = f.Password + } } else { - if err = f.ReadPasswordFromUser(); err != nil { + if f.LocalConfig.Password == "" { + f.LocalConfig.Password = f.Password + } else if f.LocalConfig.Password != f.Password { + log.Error("password does not match config file password") return utils.MissingOrIncorrectPassword } - f.LocalConfig.Password = f.Password - } - } else { - if f.LocalConfig.Password == "" { - f.LocalConfig.Password = f.Password - } else if f.LocalConfig.Password != f.Password { - log.Error("password does not match config file password") - return utils.MissingOrIncorrectPassword } } return nil @@ -215,10 +244,31 @@ func (f *Flags) handleSetAMTFeatures() error { f.flagSetAMTFeatures.BoolVar(&f.IDER, "ider", false, "Enables or Disables IDER (IDE Redirection)") f.flagSetAMTFeatures.StringVar(&f.Password, "password", f.lookupEnvOrString("AMT_PASSWORD", ""), "AMT password") + // V2 features + f.flagSetAMTFeatures.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + f.flagSetAMTFeatures.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") + if err = f.flagSetAMTFeatures.Parse(f.commandLineArgs[3:]); err != nil { f.printConfigurationUsage() return utils.IncorrectCommandLineParameters } + + if f.configContentV2 != "" { + err := f.handleLocalConfigV2() + if err != nil { + return utils.FailedReadingConfiguration + } + + // Set the values from the v2 config file. + if f.LocalConfigV2.Configuration.Redirection.UserConsent != "" { + f.UserConsent = f.LocalConfigV2.Configuration.Redirection.UserConsent + } + f.KVM = f.LocalConfigV2.Configuration.Redirection.Services.KVM + f.SOL = f.LocalConfigV2.Configuration.Redirection.Services.SOL + f.IDER = f.LocalConfigV2.Configuration.Redirection.Services.IDER + f.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + } + // Validate UserConsent if f.UserConsent != "" { f.UserConsent = strings.ToLower(f.UserConsent) @@ -241,6 +291,9 @@ func (f *Flags) handleMEBxPassword() error { f.flagSetMEBx.BoolVar(&f.JsonOutput, "json", false, "JSON output") f.flagSetMEBx.StringVar(&f.Password, "password", f.lookupEnvOrString("AMT_PASSWORD", ""), "AMT password") f.flagSetMEBx.StringVar(&f.MEBxPassword, "mebxpassword", f.lookupEnvOrString("MEBX_PASSWORD", ""), "MEBX password") + // V2 features + f.flagSetMEBx.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + f.flagSetMEBx.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") if len(f.commandLineArgs) > 3 { if err := f.flagSetMEBx.Parse(f.commandLineArgs[3:]); err != nil { @@ -249,6 +302,17 @@ func (f *Flags) handleMEBxPassword() error { } } + if f.configContentV2 != "" { + err := f.handleLocalConfigV2() + if err != nil { + return utils.FailedReadingConfiguration + } + + // Set the values from the v2 config file. + f.MEBxPassword = f.LocalConfigV2.Configuration.AMTSpecific.MEBXPassword + f.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + } + if f.Password == "" { if rc := f.ReadPasswordFromUser(); rc != nil { return rc @@ -308,6 +372,10 @@ func (f *Flags) handleConfigureTLS() error { fs.StringVar(&f.ConfigTLSInfo.EAUsername, "eaUsername", "", "Enterprise Assistant username") fs.StringVar(&f.ConfigTLSInfo.EAPassword, "eaPassword", "", "Enterprise Assistant password") + // V2 features + fs.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + fs.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") + if len(f.commandLineArgs) < (3 + 0) { fs.Usage() return utils.IncorrectCommandLineParameters @@ -320,6 +388,26 @@ func (f *Flags) handleConfigureTLS() error { fs.Usage() return utils.IncorrectCommandLineParameters } + + if f.configContentV2 != "" { + err := f.handleLocalConfigV2() + if err != nil { + return utils.FailedReadingConfiguration + } + f.LocalConfig.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + mutualAuth := f.LocalConfigV2.Configuration.TLS.MutualAuthentication + enabled := f.LocalConfigV2.Configuration.TLS.Enabled + allowNonTLS := f.LocalConfigV2.Configuration.TLS.AllowNonTLS + mode := f.DetermineTLSMode(mutualAuth, enabled, allowNonTLS) + f.ConfigTLSInfo.TLSMode, _ = ParseTLSMode(mode) + // ToDo: No need check whether it has to include in config file or default value to 3 + f.ConfigTLSInfo.DelayInSeconds = 3 + f.ConfigTLSInfo.EAAddress = f.LocalConfigV2.Configuration.EnterpriseAssistant.URL + f.ConfigTLSInfo.EAUsername = f.LocalConfigV2.Configuration.EnterpriseAssistant.Username + f.ConfigTLSInfo.EAPassword = f.LocalConfigV2.Configuration.EnterpriseAssistant.Password + + } + if f.configContent != "" { err := f.handleLocalConfig() if err != nil { @@ -344,11 +432,32 @@ func (f *Flags) handleConfigureTLS() error { return nil } +func (f *Flags) DetermineTLSMode(mutualAuth, enabled, allowNonTLS bool) string { + switch { + case enabled && !allowNonTLS && !mutualAuth: + return "Server" + case enabled && allowNonTLS && !mutualAuth: + return "ServerAndNonTLS" + case enabled && !allowNonTLS && mutualAuth: + return "Mutual" + case enabled && allowNonTLS && mutualAuth: + return "MutualAndNonTLS" + case !enabled: + return "None" + default: + return "Unknown" + } +} + func (f *Flags) handleAddEthernetSettings() error { var configJson string var secretsFilePath string var secretConfig config.SecretConfig + // V2 features + f.flagSetAddEthernetSettings.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + f.flagSetAddEthernetSettings.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") + f.flagSetAddEthernetSettings.StringVar(&f.configContent, "config", "", "specify a config file or smb: file share URL") f.flagSetAddEthernetSettings.StringVar(&configJson, "configJson", "", "configuration as a JSON string") f.flagSetAddEthernetSettings.StringVar(&secretsFilePath, "secrets", "", "specify a secrets file ") @@ -396,6 +505,42 @@ func (f *Flags) handleAddEthernetSettings() error { f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xCfg) f.LocalConfig.EnterpriseAssistant = eaSettings + if f.configContentV2 != "" && f.configV2Key != "" { + err := f.handleLocalConfigV2() + if err != nil { + return utils.FailedReadingConfiguration + } + + f.LocalConfig.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + f.LocalConfig.WiredConfig.DHCP = f.LocalConfigV2.Configuration.Network.Wired.DHCPEnabled + f.LocalConfig.WiredConfig.Static = f.LocalConfigV2.Configuration.Network.Wired.SharedStaticIP + f.LocalConfig.WiredConfig.IpSync = f.LocalConfigV2.Configuration.Network.Wired.IPSyncEnabled + f.LocalConfig.WiredConfig.IpAddress = f.LocalConfigV2.Configuration.Network.Wired.IPAddress + f.LocalConfig.WiredConfig.Subnetmask = f.LocalConfigV2.Configuration.Network.Wired.SubnetMask + f.LocalConfig.WiredConfig.Gateway = f.LocalConfigV2.Configuration.Network.Wired.DefaultGateway + f.LocalConfig.WiredConfig.PrimaryDNS = f.LocalConfigV2.Configuration.Network.Wired.PrimaryDNS + f.LocalConfig.WiredConfig.SecondaryDNS = f.LocalConfigV2.Configuration.Network.Wired.SecondaryDNS + + if f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x != nil { + f.LocalConfig.WiredConfig.Ieee8021xProfileName = "wiredIEEE8021x" + f.LocalConfig.Ieee8021xConfigs[0].ProfileName = "wiredIEEE8021x" + f.LocalConfig.Ieee8021xConfigs[0].Username = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.Username + f.LocalConfig.Ieee8021xConfigs[0].Password = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.Password + f.LocalConfig.Ieee8021xConfigs[0].AuthenticationProtocol = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.AuthenticationProtocol + f.LocalConfig.Ieee8021xConfigs[0].ClientCert = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.ClientCert + f.LocalConfig.Ieee8021xConfigs[0].CACert = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.CACert + f.LocalConfig.Ieee8021xConfigs[0].PrivateKey = f.LocalConfigV2.Configuration.Network.Wired.IEEE8021x.PrivateKey + + if !f.LocalConfig.EnterpriseAssistant.EAConfigured { + f.LocalConfig.EnterpriseAssistant.EAAddress = f.LocalConfigV2.Configuration.EnterpriseAssistant.URL + f.LocalConfig.EnterpriseAssistant.EAUsername = f.LocalConfigV2.Configuration.EnterpriseAssistant.Username + f.LocalConfig.EnterpriseAssistant.EAPassword = f.LocalConfigV2.Configuration.EnterpriseAssistant.Password + f.LocalConfig.EnterpriseAssistant.EAConfigured = true + } + } + + } + if f.configContent != "" || configJson != "" { err := f.handleLocalConfig() if err != nil { @@ -526,6 +671,11 @@ func (f *Flags) handleAddWifiSettings() error { var secretsFilePath string var wifiSecretConfig config.SecretConfig var configJson string + + // V2 features + f.flagSetAddWifiSettings.StringVar(&f.configContentV2, "configv2", "", "specify a config file or smb: file share URL") + f.flagSetAddWifiSettings.StringVar(&f.configV2Key, "configencryptionkey", f.lookupEnvOrString("CONFIG_ENCRYPTION_KEY", ""), "provide the 32 byte key to decrypt the config file") + f.flagSetAddWifiSettings.StringVar(&f.configContent, "config", "", "specify a config file or smb: file share URL") f.flagSetAddWifiSettings.StringVar(&configJson, "configJson", "", "configuration as a JSON string") f.flagSetAddWifiSettings.StringVar(&secretsFilePath, "secrets", "", "specify a secrets file ") @@ -582,15 +732,75 @@ func (f *Flags) handleAddWifiSettings() error { f.LocalConfig.EnterpriseAssistant = eaSettings eaSettings.EAConfigured = false - err = f.handleLocalConfig() - if err != nil { - return utils.FailedReadingConfiguration - } - if configJson != "" { - err := json.Unmarshal([]byte(configJson), &f.LocalConfig) + if f.configContentV2 != "" && f.configV2Key != "" { + f.LocalConfig.WifiConfigs = []config.WifiConfig{} + f.LocalConfig.Ieee8021xConfigs = []config.Ieee8021xConfig{} + f.LocalConfig.EnterpriseAssistant = config.EnterpriseAssistant{EAConfigured: false} + err := f.handleLocalConfigV2() if err != nil { - log.Error(err) - return utils.IncorrectCommandLineParameters + return utils.FailedReadingConfiguration + } + + f.LocalConfig.Password = f.LocalConfigV2.Configuration.AMTSpecific.AdminPassword + + for i, wifiCfg := range f.LocalConfigV2.Configuration.Network.Wireless.Profiles { + authMethod, err := f.getAuthenticationCode(wifiCfg.AuthenticationMethod) + if err != nil { + log.Error("Failed to get authentication code", err) + return err + } + + encryptionMethod, err := f.getEncrytionCode(wifiCfg.EncryptionMethod) + if err != nil { + log.Error("Failed to get encryption code", err) + return err + } + + newWifiConfig := config.WifiConfig{ + ProfileName: fmt.Sprintf("profile%d", i+1), + SSID: wifiCfg.SSID, + Priority: wifiCfg.Priority, + AuthenticationMethod: authMethod, + EncryptionMethod: encryptionMethod, + PskPassphrase: wifiCfg.Password, + } + + // Handle 802.1x configurations + if newWifiConfig.AuthenticationMethod == int(wifi.AuthenticationMethodWPAIEEE8021x) || newWifiConfig.AuthenticationMethod == int(wifi.AuthenticationMethodWPA2IEEE8021x) { + // Add corresponding 802.1x config + ieee8021xConfig := config.Ieee8021xConfig{ + ProfileName: newWifiConfig.ProfileName, + Username: wifiCfg.IEEE8021x.Username, + Password: wifiCfg.IEEE8021x.Password, + AuthenticationProtocol: wifiCfg.IEEE8021x.AuthenticationProtocol, + ClientCert: wifiCfg.IEEE8021x.ClientCert, + CACert: wifiCfg.IEEE8021x.CACert, + PrivateKey: wifiCfg.IEEE8021x.PrivateKey, + } + f.LocalConfig.Ieee8021xConfigs = append(f.LocalConfig.Ieee8021xConfigs, ieee8021xConfig) + + if !f.LocalConfig.EnterpriseAssistant.EAConfigured { + f.LocalConfig.EnterpriseAssistant.EAAddress = f.LocalConfigV2.Configuration.EnterpriseAssistant.URL + f.LocalConfig.EnterpriseAssistant.EAUsername = f.LocalConfigV2.Configuration.EnterpriseAssistant.Username + f.LocalConfig.EnterpriseAssistant.EAPassword = f.LocalConfigV2.Configuration.EnterpriseAssistant.Password + f.LocalConfig.EnterpriseAssistant.EAConfigured = true + } + } + + f.LocalConfig.WifiConfigs = append(f.LocalConfig.WifiConfigs, newWifiConfig) + } + + } else { + err = f.handleLocalConfig() + if err != nil { + return utils.FailedReadingConfiguration + } + if configJson != "" { + err := json.Unmarshal([]byte(configJson), &f.LocalConfig) + if err != nil { + log.Error(err) + return utils.IncorrectCommandLineParameters + } } } @@ -626,6 +836,24 @@ func (f *Flags) handleAddWifiSettings() error { return nil } +func (f *Flags) getAuthenticationCode(s string) (int, error) { + for methodType, code := range authenticationMethod { + if strings.EqualFold(s, methodType) { + return int(code), nil + } + } + return 0, utils.MissingOrInvalidConfiguration +} + +func (f *Flags) getEncrytionCode(s string) (int, error) { + for methodType, code := range encryptionMethod { + if strings.EqualFold(s, methodType) { + return int(code), nil + } + } + return 0, utils.MissingOrInvalidConfiguration +} + func (f *Flags) mergeWifiSecrets(wifiSecretConfig config.SecretConfig) error { for _, secret := range wifiSecretConfig.Secrets { if secret.ProfileName == "" { @@ -752,9 +980,11 @@ func (f *Flags) verifyWifiConfigurations() error { log.Errorf("wifi configuration for 8021x contains passphrase: %s", cfg.ProfileName) return utils.MissingOrInvalidConfiguration } - err := f.verifyMatchingIeee8021xConfig(cfg.Ieee8021xProfileName) - if err != nil { - return err + if f.configContentV2 == "" { // Not required when config is deprecated + err := f.verifyMatchingIeee8021xConfig(cfg.Ieee8021xProfileName) + if err != nil { + return err + } } case wifi.AuthenticationMethodOther: log.Errorf("unsupported AuthenticationMethod_Other (%d) for config: %s", cfg.AuthenticationMethod, cfg.ProfileName) @@ -807,7 +1037,7 @@ func (f *Flags) verifyMatchingIeee8021xConfig(profileName string) error { continue } if foundOne { - log.Error("duplicate IEEE802x Profile names: ", ieee802xCfg.ProfileName) + log.Error("duplicate IEEE8021x Profile names: ", ieee802xCfg.ProfileName) return utils.MissingOrInvalidConfiguration } @@ -818,7 +1048,7 @@ func (f *Flags) verifyMatchingIeee8021xConfig(profileName string) error { } } if !foundOne { - log.Error("missing IEEE802x Profile: ", profileName) + log.Error("missing IEEE8021x Profile: ", profileName) return utils.MissingOrInvalidConfiguration } return nil diff --git a/internal/flags/flags.go b/internal/flags/flags.go index 82880dab..45aae814 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -7,6 +7,7 @@ package flags import ( "bytes" "encoding/base64" + "encoding/json" "flag" "fmt" "net" @@ -20,6 +21,9 @@ import ( "strings" "time" + configv2 "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/config" + "github.com/open-amt-cloud-toolkit/go-wsman-messages/v2/pkg/security" + "github.com/google/uuid" "github.com/ilyakaznacheev/cleanenv" @@ -76,8 +80,11 @@ type Flags struct { UseACM bool EchoPass bool configContent string + configContentV2 string + configV2Key string UUID string LocalConfig config.Config + LocalConfigV2 configv2.Configuration amtInfoCommand *flag.FlagSet amtActivateCommand *flag.FlagSet amtDeactivateCommand *flag.FlagSet @@ -345,3 +352,25 @@ func (f *Flags) handleLocalConfig() error { } return nil } + +func (f *Flags) handleLocalConfigV2() error { + if f.configV2Key == "" { + log.Error("config error: missing encryption key") + return utils.FailedReadingConfiguration + } + + security := security.Crypto{EncryptionKey: f.configV2Key} + content, err := security.ReadAndDecryptFile(f.configContentV2) + if err != nil { + log.Error("config error: ", err) + return err + } + + _, err = json.MarshalIndent(content, "", " ") + if err != nil { + log.Error("error formatting config content: ", err) + return err + } + f.LocalConfigV2 = content + return nil +} diff --git a/internal/local/tls.go b/internal/local/tls.go index 65fd75e1..cc3bc718 100644 --- a/internal/local/tls.go +++ b/internal/local/tls.go @@ -23,18 +23,21 @@ const LocalTLSInstanceId = `Intel(r) AMT LMS TLS Settings` func (service *ProvisioningService) ConfigureTLS() error { var err error - if service.flags.ConfigTLSInfo.EAAddress != "" && service.flags.ConfigTLSInfo.EAUsername != "" && service.flags.ConfigTLSInfo.EAPassword != "" { - err = service.ValidateURL(service.flags.ConfigTLSInfo.EAAddress) + if service.flags.ConfigTLSInfo.TLSMode != flags.TLSModeDisabled { + if service.flags.ConfigTLSInfo.EAAddress != "" && service.flags.ConfigTLSInfo.EAUsername != "" && service.flags.ConfigTLSInfo.EAPassword != "" { + err = service.ValidateURL(service.flags.ConfigTLSInfo.EAAddress) + if err != nil { + log.Error("url validation failed: ", err) + return utils.TLSConfigurationFailed + } + err = service.ConfigureTLSWithEA() + } else { + err = service.ConfigureTLSWithSelfSignedCert() + } + if err != nil { - log.Error("url validation failed: ", err) - return utils.TLSConfigurationFailed + return err } - err = service.ConfigureTLSWithEA() - } else { - err = service.ConfigureTLSWithSelfSignedCert() - } - if err != nil { - return err } err = service.SynchronizeTime() @@ -252,7 +255,7 @@ func (service *ProvisioningService) CreateTLSCredentialContext(certHandle string } func (service *ProvisioningService) EnableTLS() error { - log.Info("enabling tls") + log.Info("Start TLS configuration : ", service.flags.ConfigTLSInfo.TLSMode.String()) enumerateRsp, err := service.interfacedWsmanMessage.EnumerateTLSSettingData() if err != nil { @@ -284,8 +287,11 @@ func (service *ProvisioningService) EnableTLS() error { } func (service *ProvisioningService) ConfigureTLSSettings(setting tls.SettingDataResponse) error { - data := getTLSSettings(setting, service.flags.ConfigTLSInfo.TLSMode) - _, err := service.interfacedWsmanMessage.PUTTLSSettings(data.InstanceID, data) + data, err := getTLSSettings(setting, service.flags.ConfigTLSInfo.TLSMode) + if err != nil { + return err + } + _, err = service.interfacedWsmanMessage.PUTTLSSettings(data.InstanceID, data) if err != nil { log.Errorf("failed to configure remote TLS Settings (%s)\n", data.InstanceID) return utils.WSMANMessageError @@ -293,7 +299,7 @@ func (service *ProvisioningService) ConfigureTLSSettings(setting tls.SettingData return nil } -func getTLSSettings(setting tls.SettingDataResponse, tlsMode flags.TLSMode) tls.SettingDataRequest { +func getTLSSettings(setting tls.SettingDataResponse, tlsMode flags.TLSMode) (tls.SettingDataRequest, error) { data := tls.SettingDataRequest{ AcceptNonSecureConnections: setting.AcceptNonSecureConnections, ElementName: setting.ElementName, @@ -301,16 +307,22 @@ func getTLSSettings(setting tls.SettingDataResponse, tlsMode flags.TLSMode) tls. InstanceID: setting.InstanceID, MutualAuthentication: setting.MutualAuthentication, } - if setting.InstanceID == RemoteTLSInstanceId { - log.Infof("configuring remote TLS settings mode: %s", tlsMode) - if setting.NonSecureConnectionsSupported == nil || *setting.NonSecureConnectionsSupported { - data.AcceptNonSecureConnections = tlsMode == flags.TLSModeServerAndNonTLS || tlsMode == flags.TLSModeMutualAndNonTLS + + log.Infof("configuring TLS settings: %s", setting.InstanceID) + if setting.NonSecureConnectionsSupported == nil || *setting.NonSecureConnectionsSupported { + data.AcceptNonSecureConnections = tlsMode == flags.TLSModeServerAndNonTLS || tlsMode == flags.TLSModeMutualAndNonTLS + } + + if setting.NonSecureConnectionsSupported != nil { + if tlsMode == flags.TLSModeDisabled && !*setting.NonSecureConnectionsSupported { + log.Errorf("TLS cannot be disabled on this device") + return tls.SettingDataRequest{}, utils.TLSConfigurationFailed } - data.MutualAuthentication = tlsMode == flags.TLSModeMutual || tlsMode == flags.TLSModeMutualAndNonTLS - } else { - log.Info("configuring local TLS settings") } - return data + data.MutualAuthentication = tlsMode == flags.TLSModeMutual || tlsMode == flags.TLSModeMutualAndNonTLS + data.Enabled = tlsMode != flags.TLSModeDisabled + + return data, nil } func (service *ProvisioningService) updateTLSCredentialContext(handles Handles) error {