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