1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
package ipmi
import (
"context"
"fmt"
)
// 13.14
// 22.13
type GetChannelAuthenticationCapabilitiesRequest struct {
// [7]
// - 1b = get IPMI v2.0+ extended data.
// If the given channel supports authentication but does not support RMCP+
// (e.g. a serial channel), then the Response data should return with bit [5] of byte 4 = 0b, byte 5 should return 01h,
//
// - 0b = Backward compatible with IPMI v1.5. Response data only returns
// bytes 1:9, bit [7] of byte 3 (Authentication Type Support) and bit [5] of byte 4 returns as 0b, bit [5] of byte byte 5 returns 00h.
// [6:4] - reserved
IPMIv20Extended bool
// [3:0] - channel number.
// 0h-Bh, Fh = channel numbers
// Eh = retrieve information for channel this request was issued on
ChannelNumber uint8
// Requested Maximum Privilege Level
MaximumPrivilegeLevel PrivilegeLevel
}
type GetChannelAuthenticationCapabilitiesResponse struct {
// Channel number that the Authentication Capabilities is being returned for.
// If the channel number in the request was set to Eh, this will return
// the channel number for the channel that the request was received on
ChannelNumber uint8
// Returns the setting of the Authentication Type Enable field from the
// configuration parameters for the given channel that corresponds to
// the Requested Maximum Privilege Level.
// [7] -
// 1b = IPMI v2.0+ extended capabilities available. See Extended Capabilities field, below.
// 0b = IPMI v1.5 support only.
IPMIv20ExtendedAvailable bool
// [5:0] - IPMI v1.5 Authentication type(s) enabled for given Requested Maximum Privilege Level
AuthTypeNoneSupported bool // bit 0
AuthTypeMD2Supported bool // bit 1
AuthTypeMD5Supported bool // bit 2
AuthTypePasswordSupported bool // bit 4
AuthTypeOEMProprietarySupported bool // bit 5
// [5] - Kg status (two-key login status).
// Applies to v2.0/RMCP+ RAKP Authentication only. Otherwise, ignore as reserved.
// 0b = Kg is set to default (all 0s).
// 1b = Kg is set to non-zero value.
KgStatus bool
// [4] - Per-message Authentication status
// 0b = Per-message Authentication is enabled.
// 1b = Per-message Authentication is disabled.
// Authentication Type "none" accepted for packets to the BMC after the session has been activated.
PerMessageAuthenticationDisabled bool
// [3] - User Level Authentication status
// 0b = User Level Authentication is enabled.
// 1b = User Level Authentication is disabled.
// Authentication Type "none" accepted for User Level commands to the BMC.
UserLevelAuthenticationDisabled bool
// [2:0] - Anonymous Login status
// This parameter returns values that tells the remote console whether
// there are users on the system that have "null" usernames.
// This can be used to guide the way the remote console presents login options to the user.
// (see IPMI v1.5 specification sections 6.9.1, "Anonymous Login" Convention and 6.9.2, Anonymous Login )
// [2] - 1b = Non-null usernames enabled. (One or more users are enabled that have non-null usernames).
// [1] - 1b = Null usernames enabled (One or more users that have a null username, but non-null password, are presently enabled)
// [0] - 1b = Anonymous Login enabled (A user that has a null username and null password is presently enabled)
NonNullUsernamesEnabled bool
NullUsernamesEnabled bool
AnonymousLoginEnabled bool
// For IPMI v1.5: - reserved
// For IPMI v2.0+: - Extended Capabilities
// [7:2] - reserved
// [1] - 1b = channel supports IPMI v2.0 connections.
// [0] - 1b = channel supports IPMI v1.5 connections.
SupportIPMIv15 bool
SupportIPMIv20 bool
// IANA Enterprise Number for OEM/Organization that specified the particular
// OEM Authentication Type for RMCP. Least significant byte first.
// ONLY 3 bytes occupied. Return 00h, 00h, 00h if no OEM authentication type available.
OEMID uint32
// Additional OEM-specific information for the OEM Authentication Type for RMCP.
// Return 00h if no OEM authentication type available.
OEMAuxiliaryData uint8
}
func (req *GetChannelAuthenticationCapabilitiesRequest) Pack() []byte {
var msg = make([]byte, 2)
byte1 := req.ChannelNumber
if req.IPMIv20Extended {
byte1 = byte1 | 0x80
}
packUint8(byte1, msg, 0)
packUint8(uint8(req.MaximumPrivilegeLevel), msg, 1)
return msg
}
func (req *GetChannelAuthenticationCapabilitiesRequest) Command() Command {
return CommandGetChannelAuthCapabilities
}
func (res *GetChannelAuthenticationCapabilitiesResponse) Unpack(msg []byte) error {
if len(msg) < 8 {
return ErrUnpackedDataTooShortWith(len(msg), 8)
}
res.ChannelNumber, _, _ = unpackUint8(msg, 0)
b, _, _ := unpackUint8(msg, 1)
res.IPMIv20ExtendedAvailable = isBit7Set(b)
res.AuthTypeOEMProprietarySupported = isBit5Set(b)
res.AuthTypePasswordSupported = isBit4Set(b)
res.AuthTypeMD5Supported = isBit2Set(b)
res.AuthTypeMD2Supported = isBit1Set(b)
c, _, _ := unpackUint8(msg, 2)
res.KgStatus = isBit5Set(c)
res.PerMessageAuthenticationDisabled = isBit4Set(c)
res.UserLevelAuthenticationDisabled = isBit3Set(c)
res.NonNullUsernamesEnabled = isBit2Set(c)
res.NullUsernamesEnabled = isBit1Set(c)
res.AnonymousLoginEnabled = isBit0Set(c)
d, _, _ := unpackUint8(msg, 3)
if res.IPMIv20ExtendedAvailable {
res.SupportIPMIv20 = isBit1Set(d)
res.SupportIPMIv15 = isBit0Set(d)
}
res.OEMID, _, _ = unpackUint24L(msg, 4)
res.OEMAuxiliaryData, _, _ = unpackUint8(msg, 7)
return nil
}
func (*GetChannelAuthenticationCapabilitiesResponse) CompletionCodes() map[uint8]string {
// no command-specific cc
return map[uint8]string{}
}
func (res *GetChannelAuthenticationCapabilitiesResponse) chooseAuthType() AuthType {
if res.AuthTypeMD2Supported {
return AuthTypeMD2
}
if res.AuthTypeMD5Supported {
return AuthTypeMD5
}
if res.AuthTypePasswordSupported {
return AuthTypePassword
}
if res.AuthTypeOEMProprietarySupported {
return AuthTypeOEM
}
if res.AuthTypeNoneSupported {
return AuthTypeNone
}
return AuthTypeNone
}
func (res *GetChannelAuthenticationCapabilitiesResponse) Format() string {
return fmt.Sprintf("%v", res)
}
// GetChannelAuthenticationCapabilities is used to retrieve capability information
// about the channel that the message is delivered over, or for a particular channel.
// The command returns the authentication algorithm support for the given privilege level.
//
// This command is sent in unauthenticated (clear) format.
//
// When activating a session, the privilege level passed in this command will
// normally be the same Requested Maximum Privilege level that will be used
// for a subsequent Activate Session command.
func (c *Client) GetChannelAuthenticationCapabilities(ctx context.Context, channelNumber uint8, privilegeLevel PrivilegeLevel) (response *GetChannelAuthenticationCapabilitiesResponse, err error) {
request := &GetChannelAuthenticationCapabilitiesRequest{
IPMIv20Extended: true,
ChannelNumber: channelNumber,
MaximumPrivilegeLevel: privilegeLevel,
}
response = &GetChannelAuthenticationCapabilitiesResponse{}
err = c.Exchange(ctx, request, response)
if err != nil {
return
}
if !response.AnonymousLoginEnabled {
if c.Username == "" {
return nil, fmt.Errorf("anonymous login is not enabled, username (%s) is empty", c.Username)
}
}
c.session.authType = response.chooseAuthType()
return
}
|