1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #ifndef nsHttpAuthCache_h__
7 #define nsHttpAuthCache_h__
8 
9 #include "nsError.h"
10 #include "nsTArray.h"
11 #include "nsClassHashtable.h"
12 #include "nsCOMPtr.h"
13 #include "nsHashKeys.h"
14 #include "nsStringFwd.h"
15 #include "nsIObserver.h"
16 
17 namespace mozilla {
18 
19 class OriginAttributesPattern;
20 
21 namespace net {
22 
23 struct nsHttpAuthPath {
24   struct nsHttpAuthPath* mNext;
GetAuthKey(const char * scheme,const char * host,int32_t port,nsACString const & originSuffix,nsCString & key)25   char mPath[1];
26 };
27 
28 //-----------------------------------------------------------------------------
29 // nsHttpAuthIdentity
30 //-----------------------------------------------------------------------------
31 
32 class nsHttpAuthIdentity {
33  public:
34   nsHttpAuthIdentity() = default;
35   nsHttpAuthIdentity(const char16_t* domain, const char16_t* user,
36                      const char16_t* password)
37       : mUser(nullptr), mPass{nullptr}, mDomain{nullptr} {
38     DebugOnly<nsresult> rv = Set(domain, user, password);
39     MOZ_ASSERT(NS_SUCCEEDED(rv));
StrEquivalent(const char16_t * a,const char16_t * b)40   }
41   ~nsHttpAuthIdentity() { Clear(); }
42 
43   const char16_t* Domain() const { return mDomain; }
44   const char16_t* User() const { return mUser; }
45   const char16_t* Password() const { return mPass; }
46 
47   [[nodiscard]] nsresult Set(const char16_t* domain, const char16_t* user,
48                              const char16_t* password);
49   [[nodiscard]] nsresult Set(const nsHttpAuthIdentity& other) {
50     return Set(other.mDomain, other.mUser, other.mPass);
51   }
52   void Clear();
nsHttpAuthCache()53 
54   bool Equals(const nsHttpAuthIdentity& ident) const;
55   bool IsEmpty() const { return !mUser; }
56 
57  private:
58   // allocated as one contiguous blob, starting at mUser.
59   char16_t* mUser{nullptr};
60   char16_t* mPass{nullptr};
61   char16_t* mDomain{nullptr};
62 };
~nsHttpAuthCache()63 
64 //-----------------------------------------------------------------------------
65 // nsHttpAuthEntry
66 //-----------------------------------------------------------------------------
67 
68 class nsHttpAuthEntry {
69  public:
70   const char* Realm() const { return mRealm; }
71   const char* Creds() const { return mCreds; }
72   const char* Challenge() const { return mChallenge; }
73   const char16_t* Domain() const { return mIdent.Domain(); }
74   const char16_t* User() const { return mIdent.User(); }
75   const char16_t* Pass() const { return mIdent.Password(); }
76   nsHttpAuthPath* RootPath() { return mRoot; }
77 
78   const nsHttpAuthIdentity& Identity() const { return mIdent; }
79 
80   [[nodiscard]] nsresult AddPath(const char* aPath);
81 
82   nsCOMPtr<nsISupports> mMetaData;
83 
84  private:
85   nsHttpAuthEntry(const char* path, const char* realm, const char* creds,
86                   const char* challenge, const nsHttpAuthIdentity* ident,
87                   nsISupports* metadata)
88       : mRoot(nullptr),
89         mTail(nullptr),
90         mRealm(nullptr),
91         mCreds{nullptr},
92         mChallenge{nullptr} {
93     DebugOnly<nsresult> rv =
94         Set(path, realm, creds, challenge, ident, metadata);
95     MOZ_ASSERT(NS_SUCCEEDED(rv));
96   }
97   ~nsHttpAuthEntry();
98 
99   [[nodiscard]] nsresult Set(const char* path, const char* realm,
100                              const char* creds, const char* challenge,
101                              const nsHttpAuthIdentity* ident,
102                              nsISupports* metadata);
103 
104   nsHttpAuthIdentity mIdent;
105 
106   nsHttpAuthPath* mRoot;  // root pointer
107   nsHttpAuthPath* mTail;  // tail pointer
108 
109   // allocated together in one blob, starting with mRealm.
110   char* mRealm;
111   char* mCreds;
112   char* mChallenge;
113 
114   friend class nsHttpAuthNode;
115   friend class nsHttpAuthCache;
116   friend class mozilla::DefaultDelete<nsHttpAuthEntry>;  // needs to call the
117                                                          // destructor
118 };
119 
120 //-----------------------------------------------------------------------------
121 // nsHttpAuthNode
122 //-----------------------------------------------------------------------------
123 
124 class nsHttpAuthNode {
125  private:
126   using EntryList = nsTArray<UniquePtr<nsHttpAuthEntry>>;
127 
128   nsHttpAuthNode();
129   ~nsHttpAuthNode();
130 
131   // path can be null, in which case we'll search for an entry
132   // with a null path.
133   nsHttpAuthEntry* LookupEntryByPath(const char* path);
134 
135   // realm must not be null
136   nsHttpAuthEntry* LookupEntryByRealm(const char* realm);
137   EntryList::const_iterator LookupEntryItrByRealm(const char* realm) const;
138 
ClearAuthEntry(const char * scheme,const char * host,int32_t port,const char * realm,nsACString const & originSuffix)139   // if a matching entry is found, then credentials will be changed.
140   [[nodiscard]] nsresult SetAuthEntry(const char* path, const char* realm,
141                                       const char* creds, const char* challenge,
142                                       const nsHttpAuthIdentity* ident,
143                                       nsISupports* metadata);
144 
145   void ClearAuthEntry(const char* realm);
146 
147   uint32_t EntryCount() { return mList.Length(); }
ClearAll()148 
149  private:
150   EntryList mList;
151 
152   friend class nsHttpAuthCache;
153   friend class mozilla::DefaultDelete<nsHttpAuthNode>;  // needs to call the
154                                                         // destructor
155 };
156 
LookupAuthNode(const char * scheme,const char * host,int32_t port,nsACString const & originSuffix,nsCString & key)157 //-----------------------------------------------------------------------------
158 // nsHttpAuthCache
159 //  (holds a hash table from host:port to nsHttpAuthNode)
160 //-----------------------------------------------------------------------------
161 
162 class nsHttpAuthCache {
163  public:
164   nsHttpAuthCache();
165   ~nsHttpAuthCache();
166 
167   // |scheme|, |host|, and |port| are required
168   // |path| can be null
169   // |entry| is either null or a weak reference
170   [[nodiscard]] nsresult GetAuthEntryForPath(const char* scheme,
171                                              const char* host, int32_t port,
172                                              const char* path,
173                                              nsACString const& originSuffix,
174                                              nsHttpAuthEntry** entry);
175 
176   // |scheme|, |host|, and |port| are required
177   // |realm| must not be null
178   // |entry| is either null or a weak reference
179   [[nodiscard]] nsresult GetAuthEntryForDomain(const char* scheme,
180                                                const char* host, int32_t port,
181                                                const char* realm,
182                                                nsACString const& originSuffix,
183                                                nsHttpAuthEntry** entry);
184 
185   // |scheme|, |host|, and |port| are required
186   // |path| can be null
187   // |realm| must not be null
188   // if |credentials|, |user|, |pass|, and |challenge| are each
189   // null, then the entry is deleted.
190   [[nodiscard]] nsresult SetAuthEntry(const char* scheme, const char* host,
191                                       int32_t port, const char* path,
192                                       const char* realm, const char* creds,
193                                       const char* challenge,
194                                       nsACString const& originSuffix,
195                                       const nsHttpAuthIdentity* ident,
196                                       nsISupports* metadata);
197 
198   void ClearAuthEntry(const char* scheme, const char* host, int32_t port,
199                       const char* realm, nsACString const& originSuffix);
200 
201   // expire all existing auth list entries including proxy auths.
202   void ClearAll();
203 
204   // For testing only.
205   void CollectKeys(nsTArray<nsCString>& aValue);
206 
207  private:
208   nsHttpAuthNode* LookupAuthNode(const char* scheme, const char* host,
209                                  int32_t port, nsACString const& originSuffix,
210                                  nsCString& key);
211 
212   class OriginClearObserver : public nsIObserver {
213     virtual ~OriginClearObserver() = default;
214 
215    public:
216     NS_DECL_ISUPPORTS
217     NS_DECL_NSIOBSERVER
218     explicit OriginClearObserver(nsHttpAuthCache* aOwner) : mOwner(aOwner) {}
219     nsHttpAuthCache* mOwner;
220   };
221 
222   void ClearOriginData(OriginAttributesPattern const& pattern);
223 
224  private:
225   using AuthNodeTable = nsClassHashtable<nsCStringHashKey, nsHttpAuthNode>;
226   AuthNodeTable mDB;  // "host:port" --> nsHttpAuthNode
227   RefPtr<OriginClearObserver> mObserver;
228 };
229 
230 }  // namespace net
231 }  // namespace mozilla
232 
233 #endif  // nsHttpAuthCache_h__
234