github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgRadius/eap/eap.go (about)

     1  package eap
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"github.com/bronze1man/kmg/third/kmgRadius/MSCHAPV2"
     9  )
    10  
    11  type Code uint8
    12  
    13  const (
    14  	CodeRequest  Code = 1
    15  	CodeResponse Code = 2
    16  	CodeSuccess  Code = 3
    17  	CodeFailure  Code = 4
    18  )
    19  
    20  func (c Code) String() string {
    21  	switch c {
    22  	case CodeRequest:
    23  		return "Request"
    24  	case CodeResponse:
    25  		return "Response"
    26  	case CodeSuccess:
    27  		return "Success"
    28  	case CodeFailure:
    29  		return "Failure"
    30  	default:
    31  		return "unknow Code " + strconv.Itoa(int(c))
    32  	}
    33  }
    34  
    35  type Type uint8
    36  
    37  const (
    38  	TypeIdentity         Type = 1
    39  	TypeNotification     Type = 2
    40  	TypeLegacyNak        Type = 3 //Response only
    41  	TypeMd5Challenge     Type = 4
    42  	TypeOneTimePassword  Type = 5 //otp
    43  	TypeGenericTokenCard Type = 6 //gtc
    44  	TypeMSCHAPV2         Type = 26
    45  	TypeExpandedTypes    Type = 254
    46  	TypeExperimentalUse  Type = 255
    47  )
    48  
    49  func (c Type) String() string {
    50  	switch c {
    51  	case TypeIdentity:
    52  		return "Identity"
    53  	case TypeNotification:
    54  		return "Notification"
    55  	case TypeLegacyNak:
    56  		return "LegacyNak"
    57  	case TypeMd5Challenge:
    58  		return "Md5Challenge"
    59  	case TypeOneTimePassword:
    60  		return "OneTimePassword"
    61  	case TypeGenericTokenCard:
    62  		return "GenericTokenCard"
    63  	case TypeMSCHAPV2:
    64  		return "MSCHAPV2"
    65  	case TypeExpandedTypes:
    66  		return "ExpandedTypes"
    67  	case TypeExperimentalUse:
    68  		return "ExperimentalUse"
    69  	default:
    70  		return "unknow Type " + strconv.Itoa(int(c))
    71  	}
    72  }
    73  
    74  type Packet interface {
    75  	Header() *PacketHeader
    76  	String() string
    77  	Encode() []byte
    78  }
    79  
    80  func Decode(b []byte) (p Packet, err error) {
    81  	if len(b) < 4 {
    82  		return nil, fmt.Errorf("[eap.Decode] protocol error input too small 1 len(b)[%d] < 4", len(b))
    83  	}
    84  	code := Code(b[0])
    85  	switch code {
    86  	case CodeRequest, CodeResponse:
    87  		if len(b) < 5 {
    88  			return nil, fmt.Errorf("[eap.Decode] protocol error input too small 1 len(b)[%d] < 5", len(b))
    89  		}
    90  		length := binary.BigEndian.Uint16(b[2:4])
    91  		if len(b) != int(length) {
    92  			return nil, fmt.Errorf("[eap.Decode] protocol error input too small 2 len(b)[%d] != int(length)[%d]", len(b), length)
    93  		}
    94  		h := PacketHeader{
    95  			Code:       Code(b[0]),
    96  			Identifier: uint8(b[1]),
    97  			Type:       Type(b[4]),
    98  		}
    99  		data := b[5:length]
   100  		switch h.Type {
   101  		case TypeIdentity:
   102  			return &IdentityPacket{
   103  				PacketHeader: h,
   104  				Identity:     string(data),
   105  			}, nil
   106  		case TypeMSCHAPV2:
   107  			MSCHAPV2, err := MSCHAPV2.Decode(data)
   108  			if err != nil {
   109  				return nil, err
   110  			}
   111  			return &MSCHAPV2Packet{
   112  				PacketHeader: h,
   113  				MSCHAPV2:     MSCHAPV2,
   114  			}, nil
   115  		case TypeLegacyNak:
   116  			if len(data) == 0 {
   117  				return nil, fmt.Errorf("[eap.Decode] Type: LegacyNak len==0")
   118  			}
   119  			return &LegacyNakPacket{
   120  				PacketHeader:    h,
   121  				DesiredAuthType: Type(data[0]),
   122  			}, nil
   123  		default:
   124  			return nil, fmt.Errorf("[eap.Decode] Type:%s not implement", h.Type)
   125  		}
   126  	case CodeSuccess, CodeFailure:
   127  		return &SimplePacket{
   128  			PacketHeader{
   129  				Code:       Code(b[0]),
   130  				Identifier: uint8(b[1]),
   131  			},
   132  		}, nil
   133  	default:
   134  		return nil, fmt.Errorf("unknow Code " + strconv.Itoa(int(code)))
   135  	}
   136  }
   137  
   138  type PacketHeader struct {
   139  	Code       Code
   140  	Identifier uint8
   141  	Type       Type //success and failure do not have any type
   142  }
   143  
   144  func (h *PacketHeader) Header() *PacketHeader {
   145  	return h
   146  }
   147  
   148  func (h *PacketHeader) String() string {
   149  	switch h.Code {
   150  	case CodeSuccess, CodeFailure:
   151  		return fmt.Sprintf("Code: %s Id:%d", h.Code, h.Identifier)
   152  	default:
   153  		return fmt.Sprintf("Code: %s Id:%d Type:%s", h.Code, h.Identifier, h.Type)
   154  	}
   155  }
   156  
   157  func (h *PacketHeader) encode(data []byte) (b []byte) {
   158  	b = make([]byte, len(data)+5)
   159  	b[0] = byte(h.Code)
   160  	b[1] = byte(h.Identifier)
   161  	binary.BigEndian.PutUint16(b[2:4], uint16(len(data)+5))
   162  	b[4] = byte(h.Type)
   163  	copy(b[5:], data)
   164  	return b
   165  }
   166  
   167  type IdentityPacket struct {
   168  	PacketHeader
   169  	Identity string
   170  }
   171  
   172  func (p *IdentityPacket) String() string {
   173  	return fmt.Sprintf("%s %s", p.PacketHeader.String(), p.Identity)
   174  }
   175  
   176  func (p *IdentityPacket) Encode() []byte {
   177  	return p.PacketHeader.encode([]byte(p.Identity))
   178  }
   179  
   180  type LegacyNakPacket struct {
   181  	PacketHeader
   182  	DesiredAuthType Type
   183  }
   184  
   185  func (p *LegacyNakPacket) String() string {
   186  	return fmt.Sprintf("%s DesiredAuthType:%s", p.PacketHeader.String(), p.DesiredAuthType)
   187  }
   188  
   189  func (p *LegacyNakPacket) Encode() []byte {
   190  	return p.PacketHeader.encode([]byte{byte(p.DesiredAuthType)})
   191  }
   192  
   193  type MSCHAPV2Packet struct {
   194  	PacketHeader
   195  	MSCHAPV2 MSCHAPV2.Packet
   196  }
   197  
   198  func (p *MSCHAPV2Packet) String() string {
   199  	return fmt.Sprintf("%s %s", p.PacketHeader.String(), p.MSCHAPV2.String())
   200  }
   201  
   202  func (p *MSCHAPV2Packet) Encode() []byte {
   203  	return p.PacketHeader.encode([]byte(p.MSCHAPV2.Encode()))
   204  }
   205  
   206  // only put code identifier
   207  type SimplePacket struct {
   208  	PacketHeader
   209  }
   210  
   211  func (p *SimplePacket) String() string {
   212  	return p.PacketHeader.String()
   213  }
   214  
   215  func (p *SimplePacket) Encode() (b []byte) {
   216  	h := p.PacketHeader
   217  	b = make([]byte, 4)
   218  	b[0] = byte(h.Code)
   219  	b[1] = byte(h.Identifier)
   220  	binary.BigEndian.PutUint16(b[2:4], uint16(4))
   221  	return b
   222  }