/// <summary> ///Sets and encrypts the User-Password attribute. ///@see TinyRadius.packet.RadiusPacket#encodeRequestAttributes(java.lang.String) /// </summary> protected override void EncodeRequestAttributes(String sharedSecret) { if (string.IsNullOrEmpty(password)) { return; } // ok for proxied packets whose CHAP password is already encrypted //throw new NotImplementedException("no password set"); if (AuthProtocol.Equals(AuthenticationType.pap)) { byte[] pass = EncodePapPassword(RadiusUtil.GetUtf8Bytes(password), RadiusUtil.GetUtf8Bytes(sharedSecret)); RemoveAttributes(USER_PASSWORD); AddAttribute(new RadiusAttribute(USER_PASSWORD, pass)); } else if (AuthProtocol.Equals(AuthenticationType.chap)) { byte[] challenge = CreateChapChallenge(); byte[] pass = EncodeChapPassword(password, challenge); RemoveAttributes(CHAP_PASSWORD); RemoveAttributes(CHAP_CHALLENGE); AddAttribute(new RadiusAttribute(CHAP_PASSWORD, pass)); AddAttribute(new RadiusAttribute(CHAP_CHALLENGE, challenge)); } }
/// <summary> ///Verifies a CHAP password against the given plaintext password. ///@return plain-text password /// </summary> private bool VerifyChapPassword(String plaintext) { if (string.IsNullOrEmpty(plaintext)) { throw new ArgumentException("plaintext must not be empty"); } if (chapChallenge == null || chapChallenge.Length != 16) { throw new RadiusException("CHAP challenge must be 16 bytes"); } if (chapPassword == null || chapPassword.Length != 17) { throw new RadiusException("CHAP password must be 17 bytes"); } byte chapIdentifier = chapPassword[0]; var byteAry = new List <byte> { chapIdentifier }; byteAry.AddRange(RadiusUtil.GetUtf8Bytes(plaintext)); byte[] chapHash = MD5.Create().ComputeHash(chapChallenge); // compar for (var i = 0; i < 16; i++) { if (chapHash[i] != chapPassword[i + 1]) { return(false); } } return(true); }
/// <summary> ///Decrypts the User-Password attribute. /// </summary> protected override void DecodeRequestAttributes(String sharedSecret) { // detect auth protocol RadiusAttribute userPassword = GetAttribute(USER_PASSWORD); RadiusAttribute chapPassword = GetAttribute(CHAP_PASSWORD); RadiusAttribute chapChallenge = GetAttribute(CHAP_CHALLENGE); if (userPassword != null) { AuthProtocol = AuthenticationType.pap; password = DecodePapPassword(userPassword.Data, RadiusUtil.GetUtf8Bytes(sharedSecret)); // copy truncated data userPassword.Data = RadiusUtil.GetUtf8Bytes(password); } else if (chapPassword != null && chapChallenge != null) { AuthProtocol = AuthenticationType.chap; this.chapPassword = chapPassword.Data; this.chapChallenge = chapChallenge.Data; } else { throw new RadiusException("Access-Request: User-Password or CHAP-Password/CHAP-Challenge missing"); } }
/** * @see AccountingRequest#updateRequestAuthenticator(String, int, byte[]) */ protected override byte[] UpdateRequestAuthenticator(String sharedSecret, int packetLength, byte[] attributes) { var authenticator = new byte[16]; /*for (int i = 0; i < 16; i++) * authenticator[i] = 0;*/ var ms = new List <byte> { Convert.ToByte(Type), Convert.ToByte(Identifier), Convert.ToByte(packetLength >> 8), Convert.ToByte(packetLength & 0xff) }; ms.AddRange(authenticator); ms.AddRange(attributes); ms.AddRange(RadiusUtil.GetUtf8Bytes(sharedSecret)); return(MD5.Create().ComputeHash(ms.ToArray())); /*MessageDigest md5 = getMd5Digest(); * md5.reset(); * md5.update((byte)getPacketType()); * md5.update((byte)getPacketIdentifier()); * md5.update((byte)(packetLength >> 8)); * md5.update((byte)(packetLength & 0xff)); * md5.update(authenticator, 0, authenticator.Length); * md5.update(attributes, 0, attributes.Length); * md5.update(RadiusUtil.getUtf8Bytes(sharedSecret)); * return md5.digest();*/ }
/// <summary> /// Creates a request authenticator for this packet. This request authenticator /// is constructed as described in RFC 2865. /// @param sharedSecret shared secret that secures the communication /// with the other Radius server/client /// @return request authenticator, 16 bytes /// </summary> protected virtual byte[] CreateRequestAuthenticator(String sharedSecret) { byte[] secretBytes = RadiusUtil.GetUtf8Bytes(sharedSecret); var randomBytes = new byte[16]; Random.NextBytes(randomBytes); var md5Bytes = new byte[secretBytes.Length + 16]; Array.Copy(secretBytes, 0, md5Bytes, 0, secretBytes.Length); Array.Copy(randomBytes, 0, md5Bytes, secretBytes.Length, 16); return(MD5.Create().ComputeHash(md5Bytes)); }
/// <summary> /// Creates an authenticator for a Radius response packet. /// @param sharedSecret shared secret /// @param packetLength Length of response packet /// @param attributes encoded attributes of response packet /// @param requestAuthenticator request packet authenticator /// @return new 16 byte response authenticator /// </summary> protected virtual byte[] CreateResponseAuthenticator(String sharedSecret, int packetLength, byte[] attributes, byte[] requestAuthenticator) { var bytes = new List <byte> { Convert.ToByte(Type), Convert.ToByte(Identifier), Convert.ToByte(packetLength >> 8), Convert.ToByte(packetLength & 0x0ff) }; bytes.AddRange(requestAuthenticator); bytes.AddRange(attributes); //bug fix from [email protected] bytes.AddRange(RadiusUtil.GetUtf8Bytes(sharedSecret)); return(MD5.Create().ComputeHash(bytes.ToArray())); }
/// <summary> ///Encodes a plain-text password using the given CHAP challenge. ///@param plaintext plain-text password ///@param chapChallenge CHAP challenge ///@return CHAP-encoded password /// </summary> private byte[] EncodeChapPassword(String plaintext, byte[] chapChallenge) { // see RFC 2865 section 2.2 var chapIdentifier = (byte)random.Next(256); var chapPassword = new byte[17]; chapPassword[0] = chapIdentifier; MD5 md5 = MD5.Create(); var aryList = new List <byte>(); aryList.Add(chapIdentifier); aryList.AddRange(RadiusUtil.GetUtf8Bytes(plaintext)); aryList.AddRange(chapChallenge); byte[] chapHash = md5.ComputeHash(aryList.ToArray()); Array.Copy(chapHash, 0, chapPassword, 1, 16); return(chapPassword); }
/// <summary> /// Calculates the request authenticator as specified by RFC 2866. /// @see TinyRadius.packet.RadiusPacket#updateRequestAuthenticator(java.lang.String, int, byte[]) /// </summary> protected override byte[] UpdateRequestAuthenticator(String sharedSecret, int packetLength, byte[] attributes) { var authenticator = new byte[16]; for (int i = 0; i < 16; i++) { authenticator[i] = 0; } var bytes = new List <byte> { (byte)Type, (byte)Identifier, (byte)(packetLength >> 8), (byte)(packetLength & 0xff) }; bytes.AddRange(authenticator); bytes.AddRange(attributes); bytes.AddRange(RadiusUtil.GetUtf8Bytes(sharedSecret)); return(MD5.Create().ComputeHash(bytes.ToArray())); }