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