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; 25 char mPath[1]; 26 }; 27 28 //----------------------------------------------------------------------------- 29 // nsHttpAuthIdentity 30 //----------------------------------------------------------------------------- 31 32 class nsHttpAuthIdentity { 33 public: nsHttpAuthIdentity()34 nsHttpAuthIdentity() : mUser(nullptr), mPass(nullptr), mDomain(nullptr) {} nsHttpAuthIdentity(const char16_t * domain,const char16_t * user,const char16_t * password)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)); 40 } ~nsHttpAuthIdentity()41 ~nsHttpAuthIdentity() { Clear(); } 42 Domain()43 const char16_t* Domain() const { return mDomain; } User()44 const char16_t* User() const { return mUser; } Password()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); Set(const nsHttpAuthIdentity & other)49 [[nodiscard]] nsresult Set(const nsHttpAuthIdentity& other) { 50 return Set(other.mDomain, other.mUser, other.mPass); 51 } 52 void Clear(); 53 54 bool Equals(const nsHttpAuthIdentity& other) const; IsEmpty()55 bool IsEmpty() const { return !mUser; } 56 57 private: 58 // allocated as one contiguous blob, starting at mUser. 59 char16_t* mUser; 60 char16_t* mPass; 61 char16_t* mDomain; 62 }; 63 64 //----------------------------------------------------------------------------- 65 // nsHttpAuthEntry 66 //----------------------------------------------------------------------------- 67 68 class nsHttpAuthEntry { 69 public: Realm()70 const char* Realm() const { return mRealm; } Creds()71 const char* Creds() const { return mCreds; } Challenge()72 const char* Challenge() const { return mChallenge; } Domain()73 const char16_t* Domain() const { return mIdent.Domain(); } User()74 const char16_t* User() const { return mIdent.User(); } Pass()75 const char16_t* Pass() const { return mIdent.Password(); } RootPath()76 nsHttpAuthPath* RootPath() { return mRoot; } 77 Identity()78 const nsHttpAuthIdentity& Identity() const { return mIdent; } 79 80 [[nodiscard]] nsresult AddPath(const char* aPath); 81 82 nsCOMPtr<nsISupports> mMetaData; 83 84 private: nsHttpAuthEntry(const char * path,const char * realm,const char * creds,const char * challenge,const nsHttpAuthIdentity * ident,nsISupports * metadata)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 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* credentials, 142 const char* challenge, 143 const nsHttpAuthIdentity* ident, 144 nsISupports* metadata); 145 146 void ClearAuthEntry(const char* realm); 147 EntryCount()148 uint32_t EntryCount() { return mList.Length(); } 149 150 private: 151 EntryList mList; 152 153 friend class nsHttpAuthCache; 154 friend class mozilla::DefaultDelete<nsHttpAuthNode>; // needs to call the 155 // destructor 156 }; 157 158 //----------------------------------------------------------------------------- 159 // nsHttpAuthCache 160 // (holds a hash table from host:port to nsHttpAuthNode) 161 //----------------------------------------------------------------------------- 162 163 class nsHttpAuthCache { 164 public: 165 nsHttpAuthCache(); 166 ~nsHttpAuthCache(); 167 168 // |scheme|, |host|, and |port| are required 169 // |path| can be null 170 // |entry| is either null or a weak reference 171 [[nodiscard]] nsresult GetAuthEntryForPath(const char* scheme, 172 const char* host, int32_t port, 173 const char* path, 174 nsACString const& originSuffix, 175 nsHttpAuthEntry** entry); 176 177 // |scheme|, |host|, and |port| are required 178 // |realm| must not be null 179 // |entry| is either null or a weak reference 180 [[nodiscard]] nsresult GetAuthEntryForDomain(const char* scheme, 181 const char* host, int32_t port, 182 const char* realm, 183 nsACString const& originSuffix, 184 nsHttpAuthEntry** entry); 185 186 // |scheme|, |host|, and |port| are required 187 // |path| can be null 188 // |realm| must not be null 189 // if |credentials|, |user|, |pass|, and |challenge| are each 190 // null, then the entry is deleted. 191 [[nodiscard]] nsresult SetAuthEntry( 192 const char* scheme, const char* host, int32_t port, const char* directory, 193 const char* realm, const char* credentials, const char* challenge, 194 nsACString const& originSuffix, const nsHttpAuthIdentity* ident, 195 nsISupports* metadata); 196 197 void ClearAuthEntry(const char* scheme, const char* host, int32_t port, 198 const char* realm, nsACString const& originSuffix); 199 200 // expire all existing auth list entries including proxy auths. 201 void ClearAll(); 202 203 private: 204 nsHttpAuthNode* LookupAuthNode(const char* scheme, const char* host, 205 int32_t port, nsACString const& originSuffix, 206 nsCString& key); 207 208 class OriginClearObserver : public nsIObserver { 209 virtual ~OriginClearObserver() = default; 210 211 public: 212 NS_DECL_ISUPPORTS 213 NS_DECL_NSIOBSERVER OriginClearObserver(nsHttpAuthCache * aOwner)214 explicit OriginClearObserver(nsHttpAuthCache* aOwner) : mOwner(aOwner) {} 215 nsHttpAuthCache* mOwner; 216 }; 217 218 void ClearOriginData(OriginAttributesPattern const& pattern); 219 220 private: 221 using AuthNodeTable = nsClassHashtable<nsCStringHashKey, nsHttpAuthNode>; 222 AuthNodeTable mDB; // "host:port" --> nsHttpAuthNode 223 RefPtr<OriginClearObserver> mObserver; 224 }; 225 226 } // namespace net 227 } // namespace mozilla 228 229 #endif // nsHttpAuthCache_h__ 230