summaryrefslogtreecommitdiffstats
path: root/source/Janrain.OpenId/Server/ServerSession.cs
blob: 6d981ac599e68978b071aadee3fd61dc79f10b54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Collections.Specialized;
using Org.Mentalis.Security.Cryptography;
using System.Text;

namespace Janrain.OpenId.Server
{
    public abstract class ServerSession
    {

        #region Private Members

        private string _session_type;

        #endregion

        #region Properties

        public string SessionType
        {
            get { return _session_type; }
            set { _session_type = value; }
        }

        #endregion

        #region Methods

        public abstract NameValueCollection Answer(byte[] secret);

        #endregion

    }

    public class PlainTextServerSession : ServerSession
    {

        #region Constructor(s)

        public PlainTextServerSession()
        {
            this.SessionType = "plaintext";
        }

        #endregion

        #region Methods

        public override NameValueCollection Answer(byte[] secret)
        {
            NameValueCollection nvc = new NameValueCollection();

            nvc.Add(QueryStringArgs.mac_key, CryptUtil.ToBase64String(secret));

            return nvc;
        }

        #endregion

    }

    public class DiffieHellmanServerSession : ServerSession
    {

        #region Private Members

        private byte[] _consumer_pubkey;
        private DiffieHellman _dh;

        #endregion

        #region Constructor(s)

        public DiffieHellmanServerSession(NameValueCollection query)
        {
            string missing;
            string dh_modulus = query.Get(QueryStringArgs.openid.dh_modulus);
            string dh_gen = query.Get(QueryStringArgs.openid.dh_gen);
            byte[] dh_modulus_bytes = new byte[0];
            byte[] dh_gen_bytes = new byte[0];

            this.SessionType = QueryStringArgs.DH_SHA1;

            if ((dh_modulus == null && dh_gen != null) ||
                (dh_gen == null && dh_modulus != null))
            {
                if (dh_modulus == null)
                    missing = "modulus";
                else
                    missing = "generator";

                throw new ProtocolException(query, "If non-default modulus or generator is supplied, both must be supplied. Missing: " + missing);
            }
            
            if (!String.IsNullOrEmpty(dh_modulus) || !String.IsNullOrEmpty(dh_gen))
            {
                try
                {
                    dh_modulus_bytes = Convert.FromBase64String(dh_modulus);                    
                }
                catch (FormatException)
                {
                    throw new ProtocolException(query, "dh_modulus isn't properly base64ed");
                }

                try
                {
                    dh_gen_bytes = Convert.FromBase64String(dh_gen);
                }
                catch (FormatException)
                {
                    throw new ProtocolException(query, "dh_gen isn't properly base64ed");
                }                
            }
            else
            {
                dh_modulus_bytes = CryptUtil.DEFAULT_MOD;
                dh_gen_bytes = CryptUtil.DEFAULT_GEN;
            }

            _dh = new DiffieHellmanManaged(dh_modulus_bytes, dh_gen_bytes, 1024);

            string consumer_pubkey = query.Get(QueryStringArgs.openid.dh_consumer_public);
            if (consumer_pubkey == null)
                throw new ProtocolException(query, "Public key for DH-SHA1 session not found in query");

            try
            {
                _consumer_pubkey = Convert.FromBase64String(consumer_pubkey);
            }
            catch (FormatException)
            {
                throw new ProtocolException(query, "consumer_pubkey isn't properly base64ed");
            }
        }

        #endregion

        #region Methods

        public override NameValueCollection Answer(byte[] secret)
        {
            byte[] mac_key = CryptUtil.SHA1XorSecret(_dh, _consumer_pubkey, secret);
            NameValueCollection nvc = new NameValueCollection();

            nvc.Add(QueryStringArgs.openidnp.dh_server_public, CryptUtil.UnsignedToBase64(_dh.CreateKeyExchange()));
            nvc.Add(QueryStringArgs.enc_mac_key, CryptUtil.ToBase64String(mac_key));

            return nvc;
        }

        #endregion

    }

}