Scott Baker | ed4efab | 2020-01-13 19:12:25 -0800 | [diff] [blame] | 1 | package types |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | |
| 6 | "gopkg.in/jcmturner/gokrb5.v7/iana/nametype" |
| 7 | ) |
| 8 | |
| 9 | // Reference: https://www.ietf.org/rfc/rfc4120.txt |
| 10 | // Section: 5.2.2 |
| 11 | |
| 12 | // PrincipalName implements RFC 4120 type: https://tools.ietf.org/html/rfc4120#section-5.2.2 |
| 13 | type PrincipalName struct { |
| 14 | NameType int32 `asn1:"explicit,tag:0"` |
| 15 | NameString []string `asn1:"generalstring,explicit,tag:1"` |
| 16 | } |
| 17 | |
| 18 | // NewPrincipalName creates a new PrincipalName from the name type int32 and name string provided. |
| 19 | func NewPrincipalName(ntype int32, spn string) PrincipalName { |
| 20 | return PrincipalName{ |
| 21 | NameType: ntype, |
| 22 | NameString: strings.Split(spn, "/"), |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | // GetSalt returns a salt derived from the PrincipalName. |
| 27 | func (pn PrincipalName) GetSalt(realm string) string { |
| 28 | var sb []byte |
| 29 | sb = append(sb, realm...) |
| 30 | for _, n := range pn.NameString { |
| 31 | sb = append(sb, n...) |
| 32 | } |
| 33 | return string(sb) |
| 34 | } |
| 35 | |
| 36 | // Equal tests if the PrincipalName is equal to the one provided. |
| 37 | func (pn PrincipalName) Equal(n PrincipalName) bool { |
| 38 | //https://tools.ietf.org/html/rfc4120#section-6.2 - the name type is not significant when checking for equivalence |
| 39 | for i, s := range pn.NameString { |
| 40 | if n.NameString[i] != s { |
| 41 | return false |
| 42 | } |
| 43 | } |
| 44 | return true |
| 45 | } |
| 46 | |
| 47 | // PrincipalNameString returns the PrincipalName in string form. |
| 48 | func (pn PrincipalName) PrincipalNameString() string { |
| 49 | return strings.Join(pn.NameString, "/") |
| 50 | } |
| 51 | |
| 52 | // ParseSPNString will parse a string in the format <service>/<name>@<realm> |
| 53 | // a PrincipalName type will be returned with the name type set to KRB_NT_PRINCIPAL(1) |
| 54 | // and the realm will be returned as a string. If the "@<realm>" suffix |
| 55 | // is not included in the SPN then the value of realm string returned will be "" |
| 56 | func ParseSPNString(spn string) (pn PrincipalName, realm string) { |
| 57 | if strings.Contains(spn, "@") { |
| 58 | s := strings.Split(spn, "@") |
| 59 | realm = s[len(s)-1] |
| 60 | spn = strings.TrimSuffix(spn, "@"+realm) |
| 61 | } |
| 62 | pn = NewPrincipalName(nametype.KRB_NT_PRINCIPAL, spn) |
| 63 | return |
| 64 | } |