Support Authorization header
authorRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 13:59:31 +0000 (13:59 +0000)
committerRichard Whitehouse <github@richardwhiuk.com>
Sun, 29 Oct 2017 13:59:31 +0000 (13:59 +0000)
src/codec.rs
src/parser.rs
src/types.rs

index 0c12300b3e7fc706a0d2ae542eff79c65ba279f9..a30485d226c82f59f8a53e9110006f9d06ff9efc 100644 (file)
@@ -429,7 +429,8 @@ mod tests {
                           "MESSAGE sip:test.com \
                            SIP/2.0\r\nAccept:text/plain\r\nAccept-Encoding:*\r\nAccept-Language:\
                            en-gb\r\nAlert-Info:<http://www.example.com/sounds/moo.wav>\r\nAllow:\
-                           MESSAGE\r\nAuthentication-Info:qop=auth\r\nVia: localhost\r\n\r\n")
+                           MESSAGE\r\nAuthentication-Info:qop=auth\r\nAuthorization:Digest \
+                           username=\"Alice\"\r\nVia: localhost\r\n\r\n")
         });
 
         let finished = request.and_then(|(socket, _request)| {
index 4d6330cba37677a9ad7befab0b9001a891e79837..4c8c03123f2b778cf97e652ffa6b5b81ffd7fbc6 100644 (file)
@@ -13,7 +13,7 @@ use types::{PathSegment, HostPort, Host, Hostname, UriParameter, UriHeader, UriH
             Scheme, Method, Transport, UserParam, Version, RequestLine, StatusLine, TopLine,
             Header, MediaType, MediaFullType, MediaParameter, MediaRange, GenericParam,
             AcceptParam, AcceptRange, Coding, Encoding, LanguageRange, Language, AlertParam, Qop,
-            AuthenticationInfo};
+            AuthenticationInfo, AuthParam, Algorithm, DigestResponse, Credentials};
 
 fn is_mark(c: u8) -> bool {
     c == b'-' || c == b'_' || c == b'.' || c == b'!' || c == b'~' || c == b'*' || c == b'\'' ||
@@ -634,6 +634,73 @@ named!(authentication_info_header<Vec<AuthenticationInfo>>, preceded!(
                tag!(b","),
                ainfo)));
 
+named!(username<Vec<u8>>, preceded!(
+       tag!(b"username="),
+       quoted_string));
+
+named!(realm<Vec<u8>>, preceded!(
+       tag!(b"realm="),
+       quoted_string));
+
+named!(nonce<Vec<u8>>, preceded!(
+       tag!(b"nonce="),
+       quoted_string));
+
+named!(digest_uri<Vec<u8>>, preceded!(
+       tag!(b"digest_uri="),
+       quoted_string));
+
+named!(dresponse<Vec<u8>>, preceded!(
+       tag!(b"response="),
+       response_digest));
+
+named!(algorithm<Algorithm>, alt!(
+       tag!("MD5") => { |_| Algorithm::MD5 } |
+       tag!("MD5-sess") => { |_| Algorithm::MD5_sess } |
+       token => { |t| Algorithm::Token(t) }
+));
+
+named!(opaque<Vec<u8>>, preceded!(
+       tag!(b"opaque="),
+       quoted_string));
+
+named!(auth_param<AuthParam>, separated_pair!(
+       token,
+       tag!(b"="),
+       alt!(
+               token |
+               quoted_string)));
+
+named!(digest_response<Vec<DigestResponse>>, many1!(alt!(
+       username => { |u| DigestResponse::Username(u) } |
+       realm => { |r| DigestResponse::Realm(r) } |
+       nonce => { |n| DigestResponse::Nonce(n) } |
+       digest_uri => { |d| DigestResponse::DigestUri(d) } |
+       dresponse => { |d| DigestResponse::Response(d) } |
+       algorithm => { |a| DigestResponse::Algorithm(a) } |
+       cnonce => { |c| DigestResponse::Cnonce(c) } |
+       opaque => { |o| DigestResponse::Opaque(o) } |
+       message_qop => { |m| DigestResponse::MessageQop(m) } |
+       nonce_count => { |n| DigestResponse::NonceCount(n) } |
+       auth_param => { |(k, v)| DigestResponse::AuthParam(k, v) })));
+
+named!(other_response<(Vec<u8>, Vec<AuthParam>)>, separated_pair!(
+       token,
+       tag!(b" "),
+       separated_nonempty_list!(
+               tag!(b","),
+               auth_param)));
+
+named!(credentials<Credentials>, alt!(
+       preceded!(
+               tag!(b"Digest "),
+               digest_response) => { |d| Credentials::Digest(d) } |
+       other_response => { |(s,p)| Credentials::Other(s, p) }));
+
+named!(authorization_header<Credentials>, preceded!(
+       tag!(b"Authorization:"),
+       credentials));
+
 named!(pub header<Header>, alt!(
 // RFC 3261 Headers
        accept_header => { |a| Header::Accept(a) } |
@@ -641,5 +708,6 @@ named!(pub header<Header>, alt!(
        accept_language_header => { |a| Header::AcceptLanguage(a) } |
        alert_info_header => { |a| Header::AlertInfo(a) } |
        allow_header => { |a| Header::Allow(a) } |
-       authentication_info_header => { |a| Header::AuthenticationInfo(a) }
+       authentication_info_header => { |a| Header::AuthenticationInfo(a) } |
+       authorization_header => { |a| Header::Authorization(a) }
 ));
index 3920bc894f4a0b07f69406a851f9022b61b311fd..e0e2cf1361f8b02042be987b44f2a435381db1e5 100644 (file)
@@ -201,6 +201,36 @@ pub enum AuthenticationInfo {
     NonceCount(Vec<u8>),
 }
 
+pub type AuthParam = (Vec<u8>, Vec<u8>);
+
+#[derive(Debug)]
+pub enum Algorithm {
+    MD5,
+    MD5_sess,
+    Token(Vec<u8>),
+}
+
+#[derive(Debug)]
+pub enum DigestResponse {
+    Username(Vec<u8>),
+    Realm(Vec<u8>),
+    Nonce(Vec<u8>),
+    DigestUri(Vec<u8>),
+    Response(Vec<u8>),
+    Algorithm(Algorithm),
+    Cnonce(Vec<u8>),
+    Opaque(Vec<u8>),
+    MessageQop(Qop),
+    NonceCount(Vec<u8>),
+    AuthParam(Vec<u8>, Vec<u8>),
+}
+
+#[derive(Debug)]
+pub enum Credentials {
+    Digest(Vec<DigestResponse>),
+    Other(Vec<u8>, Vec<AuthParam>),
+}
+
 #[derive(Debug)]
 pub enum Header {
     Accept(Vec<AcceptRange>),
@@ -209,6 +239,7 @@ pub enum Header {
     AlertInfo(Vec<AlertParam>),
     Allow(Vec<Method>),
     AuthenticationInfo(Vec<AuthenticationInfo>),
+    Authorization(Credentials),
     From(Uri),
     To(Uri),
     Extension { name: String, value: String },