Ejemplo n.º 1
0
        public void Process(Request request, Response response)
        {
            //  Is this processable?
            if (response.StatusCode != StatusCode.Unauthorized ||
                response.ContentFormat != 65008)
            {
                return;
            }

            try {
                //  Init from the response data
                Oauth.AsInfo info = new Oauth.AsInfo(response.Payload);

                //  Missage this as needed.
                string aSServer = info.ASServer;

                //  Need to build one from scratch

                if (!authServers.ContainsKey(info.ASServer))
                {
                    Console.WriteLine($"No security association is setup for {info.ASServer}");
                    return;
                }

                AuthServerInfo asi = authServers[info.ASServer];

                if (asi.ClientLink == null)
                {
                    asi.ClientLink = new CoapClient(new Uri(info.ASServer));
                    if (asi.UseDTLS)
                    {
                        asi.ClientLink.EndPoint = new DTLSClientEndPoint(asi.TlsKey);
                        asi.ClientLink.EndPoint.Start();
                    }
                }

                // M00BUG - need to make sure that this will pickup a port number if given.
                string audience = $"{request.URI.Scheme}://{request.URI.Authority}";

                Oauth.Request myRequest = new Oauth.Request("client_credentials")
                {
                    Audience = audience,
                    Scope    = CBORObject.FromObject(request.UriPath)
                };

                myRequest.Profile = Profile;

                byte[] payload = myRequest.EncodeToBytes();

                asi.ClientLink.Timeout = 2 * 60 * 1000;
                Response asResponse = asi.ClientLink.Post(payload, MediaType.ApplicationCbor);


                if (asResponse == null)
                {
                    asi.ClientLink.EndPoint.Stop();
                    asi.ClientLink = null;
                    Console.WriteLine($"Timed out requesting token from {info.ASServer}");
                    return;
                }

                if (asResponse.StatusCode != StatusCode.Created)
                {
                    //  We had an error condition appear
                    if (asResponse.Payload != null)
                    {
                        CBORObject obj       = CBORObject.DecodeFromBytes(asResponse.Payload);
                        int        error     = obj["error"].AsInt32();
                        string     errorText = "";
                        if (obj.ContainsKey("error_description"))
                        {
                            errorText = obj["error_description"].AsString();
                        }
                        Console.WriteLine(
                            $"Recieved an error {asResponse.StatusCode} with error no = {error} and description '{errorText}'");
                    }
                    else
                    {
                        Console.WriteLine($"Received and error {asResponse.StatusCode} from the AS but no text");
                    }

                    return;
                }

                Oauth.Response myResponse = new Oauth.Response(asResponse.Payload);


                // default profile for client -
#if false
                if (Profile != null && myResponse.Profile != Profile)
                {
                    Console.WriteLine("AS Server returned an unexpected profile {0}", myResponse.Profile);
                    return;
                }
#endif
                myResponse.Profile = Oauth.ProfileIds.Coap_Dtls;

                //  Post token to resource server

                CoapClient client = new CoapClient();
                client.Uri     = new Uri($"coap://{request.URI.Authority}/authz-info");
                client.Timeout = 10000; // 1 second
                Response tknResponse = client.Post(myResponse.Token, MediaType.ApplicationCbor);
                if (tknResponse == null)
                {
                    Console.WriteLine("Post of token failed w/ no response");
                    return;
                }

                if (tknResponse.StatusCode != StatusCode.Created)
                {
                    Console.WriteLine($"Post of token failed with error {tknResponse.StatusCode}");
                    return;
                }

                Confirmation cnf = myResponse.Confirmation;


                Request newRequest = new Request(request.Method);
                newRequest.Payload = request.Payload;
                newRequest.SetOptions(request.GetOptions());

                DTLSClientEndPoint endPoint = null;

                switch (myResponse.Profile)
                {
                case Oauth.ProfileIds.Coap_Dtls: {
                    OneKey key = cnf.Key;
                    endPoint = new DTLSClientEndPoint(cnf.Key);
                    endPoint.Start();

                    newRequest.EndPoint = endPoint;
                    newRequest.URI      = new Uri($"coaps://{request.URI.Authority}/{request.URI.AbsolutePath}");
                }
                break;

                case Oauth.ProfileIds.Coap_Oscore: {
                    OneKey oneKey = cnf.Key;
                    byte[] salt   = null;
                    if (oneKey.ContainsName("slt"))
                    {
                        salt = oneKey[CBORObject.FromObject("slt")].GetByteString();
                    }
                    CBORObject alg = null;
                    if (oneKey.ContainsName(CoseKeyKeys.Algorithm))
                    {
                        alg = oneKey[CoseKeyKeys.Algorithm];
                    }
                    CBORObject kdf = null;
                    if (oneKey.ContainsName(CBORObject.FromObject("kdf")))
                    {
                        kdf = oneKey[CBORObject.FromObject("kdf")];
                    }

                    SecurityContext oscoapContext = SecurityContext.DeriveContext(
                        oneKey[CoseKeyParameterKeys.Octet_k].GetByteString(),
                        oneKey[CBORObject.FromObject("sid")].GetByteString(),
                        oneKey[CBORObject.FromObject("rid")].GetByteString(),
                        salt, alg, kdf);
                    newRequest.OscoapContext = oscoapContext;
                }
                break;

                default:
                    Console.WriteLine("Cannot rewrite as we don't recognize the profile");
                    return;
                }

                newRequest.Respond += delegate(Object sender, ResponseEventArgs e)
                {
                    Response responseN = e.Response;
                    if (responseN == null)
                    {
                        Console.WriteLine("Request timeout");
                    }
                    else
                    {
                        Console.WriteLine(Utils.ToString(responseN));
                        Console.WriteLine("Time (ms): " + responseN.RTT);
                    }

                    if (endPoint != null)
                    {
                        endPoint.Stop();
                    }
                };

                newRequest.Send();
            }
            catch (Exception e) {
                Console.WriteLine("Error processing AceAuthz - " + e.ToString());
            }
        }
Ejemplo n.º 2
0
        public void Process(Request request, Response response)
        {
            //  Is this processable?
            if (response.StatusCode != StatusCode.Unauthorized /* ||
                                                                * !(response.ContentFormat == 65008 || response.ContentFormat == MediaType.ApplicationCbor)*/)
            {
                return;
            }

            try {
                //  Init from the response data
                Oauth.AsInfo info = new Oauth.AsInfo(response.Payload);

                //  Massage this as needed.
                string aSServer = info.ASServer;

                //  Need to build one from scratch

                if (!authServers.ContainsKey(info.ASServer))
                {
                    Console.WriteLine($"No security association is setup for {info.ASServer}");
                    return;
                }

                AuthServerInfo asi = authServers[info.ASServer];

                if (asi.ClientLink == null)
                {
                    asi.ClientLink = new CoapClient(new Uri(info.ASServer));
                    if (asi.UseDTLS)
                    {
                        asi.ClientLink.EndPoint = new DTLSClientEndPoint(asi.TlsKey);
                        asi.ClientLink.EndPoint.Start();
                    }
                    else
                    {
                        if (asi.ClientLink.Uri.Scheme == "coaps")
                        {
                            asi.ClientLink.Uri = new Uri($"coap://{asi.ClientLink.Uri.Authority}/{asi.ClientLink.UriPath}");
                        }
                        asi.ClientLink.OscoreContext = asi.OscoreKey;
                    }
                }

                // M00BUG - need to make sure that this will pickup a port number if given.
                string audience = $"{request.URI.Scheme}://{request.URI.Authority}";
                if (UseAudience != null)
                {
                    audience = UseAudience;
                }

                Oauth.Request myRequest = new Oauth.Request("client_credentials")
                {
                    Audience = audience,
                    Scope    = (UseScopeValue == null) ? CBORObject.FromObject(request.UriPath) : UseScopeValue
                };

                if (ClientKey != null)
                {
                    myRequest.Cnf = new Confirmation();
                    switch (ClientKeyType)
                    {
                    case 1: // kid
                        myRequest.Cnf.Kid = ClientKey.PrivateKey[CoseKeyKeys.KeyIdentifier].GetByteString();
                        break;

                    case 2: // key
                        myRequest.Cnf.Key = ClientKey.PrivateKey;
                        break;
                    }
                }

                Response asResponse;
                if (asi.UseJSON)
                {
                    string jsonPayload = myRequest.EncodeToString();
                    asi.ClientLink.Timeout = 2 * 60 * 1000;
                    asResponse             = asi.ClientLink.Post(jsonPayload, MediaType.ApplicationJson);
                }
                else
                {
                    byte[] payload = myRequest.EncodeToBytes();
                    asi.ClientLink.Timeout = 2 * 60 * 1000;
                    asResponse             = asi.ClientLink.Post(payload, MediaType.ApplicationCbor);
                }


                if (asResponse == null)
                {
                    asi.ClientLink.EndPoint.Stop();
                    asi.ClientLink = null;
                    Console.WriteLine($"Timed out requesting token from {info.ASServer}");
                    return;
                }

                if (asResponse.StatusCode != StatusCode.Created)
                {
                    //  We had an error condition appear
                    if (asResponse.Payload != null)
                    {
                        CBORObject obj       = CBORObject.DecodeFromBytes(asResponse.Payload);
                        int        error     = obj[/*"error"*/ CBORObject.FromObject(15)].AsInt32();
                        string     errorText = "";
                        if (obj.ContainsKey(/*"error_description")*/ CBORObject.FromObject(16)))
                        {
                            errorText = obj[CBORObject.FromObject(16)].AsString();
                        }
                        Console.WriteLine(
                            $"Received an error {asResponse.StatusCode} with error no = {error} and description '{errorText}'");
                    }
                    else
                    {
                        Console.WriteLine($"Received and error {asResponse.StatusCode} from the AS but no text");
                    }

                    return;
                }

                Oauth.Response myResponse = Oauth.Response.FromCBOR(asResponse.Payload);


                // default profile for client -
#if false
                if (Profile != null && myResponse.Profile != Profile)
                {
                    Console.WriteLine("AS Server returned an unexpected profile {0}", myResponse.Profile);
                    return;
                }
#endif
                if (!myResponse.ContainsKey(Oauth.Oauth_Parameter.Profile))
                {
                    myResponse.Profile = Oauth.ProfileIds.Coap_Dtls;
                }

                //  Post token to resource server

                byte[][] OscoreSalts = null;

                if (!SendTokenAsPsk)
                {
                    CoapClient client = new CoapClient();
                    client.Uri     = new Uri($"coap://{request.URI.Authority}/authz-info");
                    client.Timeout = 10000; // 1 second

                    Response tknResponse = null;
                    if (myResponse.Profile == Oauth.ProfileIds.Coap_Oscore)
                    {
                        byte[]     mySalt = new byte[] { 32, 33, 34, 35, 36, 37, 38 };
                        CBORObject post   = CBORObject.NewMap();
                        post.Add((CBORObject)Oauth.Oauth_Parameter.Access_Token, myResponse.Token);
                        post.Add((CBORObject)Oauth.Oauth_Parameter.CNonce, mySalt);
                        tknResponse = client.Post(post.EncodeToBytes(), MediaType.ApplicationAceCbor);
                        OscoreSalts = new byte[][] { mySalt, null };
                    }
                    else
                    {
                        tknResponse = client.Post(myResponse.Token, MediaType.ApplicationOctetStream);
                    }

                    if (tknResponse == null)
                    {
                        Console.WriteLine("Post of token failed w/ no response");
                        return;
                    }

                    if (tknResponse.StatusCode != StatusCode.Created)
                    {
                        Console.WriteLine($"Post of token failed with error {tknResponse.StatusCode}");
                        return;
                    }

                    if (tknResponse.ContentType == MediaType.ApplicationAceCbor)
                    {
                        CBORObject post = CBORObject.DecodeFromBytes(tknResponse.Payload);
                        if (post.ContainsKey((CBORObject)Oauth.Oauth_Parameter.Client_id))
                        {
                            //  Retrieve
                        }

                        if (post.ContainsKey((CBORObject)Oauth.Oauth_Parameter.CNonce))
                        {
                            if (OscoreSalts == null)
                            {
                                throw new Exception("Internal Error - salts");
                            }
                            OscoreSalts[1] = post[(CBORObject)Oauth.Oauth_Parameter.CNonce].GetByteString();
                        }
                    }
                }

                Confirmation cnf = myResponse.Confirmation;
                if (cnf == null)
                {
                    if (ClientKey == null)
                    {
                        Console.WriteLine("Returned a token but I don't know what key I should be using");
                        return;
                    }
                    cnf = new Confirmation(ClientKey.PrivateKey);
                }

                if (cnf.Kid != null)
                {
                    Console.WriteLine("Missing code - how do we map a kid to a real key?");
                    return;
                }

                Request newRequest = new Request(request.Method);
                newRequest.Payload = request.Payload;
                newRequest.SetOptions(request.GetOptions());

                DTLSClientEndPoint endPoint = null;

                switch (myResponse.Profile)
                {
                case Oauth.ProfileIds.Coap_Dtls: {
                    OneKey key = cnf.Key;
                    LastKeyFound = cnf.Key;
                    if (SendTokenAsPsk)
                    {
                        cnf.Key.AsCBOR().Set(CoseKeyKeys.KeyIdentifier, CBORObject.FromObject(myResponse.Token));
                    }

                    endPoint = new DTLSClientEndPoint(cnf.Key);
                    endPoint.Start();

                    if (myResponse.RsConfirmation != null)
                    {
                        ResourceInfo rsInfo = new ResourceInfo(myResponse.RsConfirmation.Key);
                        endPoint.TlsEventHandler += rsInfo.CheckRPK;
                    }

                    newRequest.EndPoint = endPoint;
                    newRequest.URI      = new Uri($"coaps://{request.URI.Authority}/{request.URI.AbsolutePath}");
                }
                break;

                case Oauth.ProfileIds.Coap_Oscore: {
                    CBORObject oscoreContext = cnf.AsCBOR[CBORObject.FromObject(Confirmation.ConfirmationIds.COSE_OSCORE)];

                    byte[] salt = new byte[0];
                    if (oscoreContext.ContainsKey(CBORObject.FromObject(6)))
                    {
                        salt = oscoreContext[CBORObject.FromObject(CBORObject.FromObject(6))].GetByteString();
                    }
                    CBORObject alg = null;
                    if (oscoreContext.ContainsKey(CBORObject.FromObject(5)))
                    {
                        alg = oscoreContext[CBORObject.FromObject(5)];
                    }
                    CBORObject kdf = null;
                    if (oscoreContext.ContainsKey(CBORObject.FromObject(4)))
                    {
                        kdf = oscoreContext[CBORObject.FromObject(4)];
                    }
                    byte[] keyContext = null;
                    if (oscoreContext.ContainsKey(CBORObject.FromObject(7)))
                    {
                        keyContext = oscoreContext[CBORObject.FromObject(7)].GetByteString();
                    }

                    if (OscoreSalts == null)
                    {
                        throw new Exception("Internal Error");
                    }

                    byte[] newSalt = new byte[salt.Length + OscoreSalts[0].Length + OscoreSalts[1].Length];
                    Array.Copy(salt, newSalt, salt.Length);
                    Array.Copy(OscoreSalts[0], 0, newSalt, salt.Length, OscoreSalts[0].Length);
                    Array.Copy(OscoreSalts[1], 0, newSalt, salt.Length + OscoreSalts[0].Length, OscoreSalts[1].Length);

                    SecurityContext oscoapContext = SecurityContext.DeriveContext(
                        oscoreContext[CBORObject.FromObject(1)].GetByteString(), keyContext,
                        oscoreContext[CBORObject.FromObject(2)].GetByteString(),
                        oscoreContext[CBORObject.FromObject(3)].GetByteString(),
                        newSalt, alg, kdf);

                    newRequest.OscoreContext = oscoapContext;

                    newRequest.URI = new Uri($"coap://{request.URI.Authority}/{request.URI.AbsolutePath}");
                }
                break;

                default:
                    Console.WriteLine("Cannot rewrite as we don't recognize the profile");
                    return;
                }

                newRequest.Respond += delegate(object sender, ResponseEventArgs e)
                {
                    Response responseN = e.Response;
                    if (responseN == null)
                    {
                        Console.WriteLine("Request timeout");
                    }
                    else
                    {
                        Console.WriteLine(Utils.ToString(responseN));
                        Console.WriteLine("Time (ms): " + responseN.RTT);
                    }

                    if (endPoint != null)
                    {
                        endPoint.Stop();
                    }
                };

                newRequest.Send();
            }
            catch (Exception e) {
                Console.WriteLine("Error processing AceAuthz - " + e.ToString());
            }
        }