LCOV - code coverage report
Current view: directory - netwerk/protocol/http - nsHttpAuthCache.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 238 199 83.6 %
Date: 2012-06-02 Functions: 27 26 96.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Darin Fisher <darin@netscape.com> (original author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include <stdlib.h>
      40                 : #include "nsHttp.h"
      41                 : #include "nsHttpAuthCache.h"
      42                 : #include "nsString.h"
      43                 : #include "nsCRT.h"
      44                 : #include "prprf.h"
      45                 : 
      46                 : static inline void
      47            3537 : GetAuthKey(const char *scheme, const char *host, PRInt32 port, nsCString &key)
      48                 : {
      49            3537 :     key.Assign(scheme);
      50            3537 :     key.AppendLiteral("://");
      51            3537 :     key.Append(host);
      52            3537 :     key.Append(':');
      53            3537 :     key.AppendInt(port);
      54            3537 : }
      55                 : 
      56                 : // return true if the two strings are equal or both empty.  an empty string
      57                 : // is either null or zero length.
      58                 : static bool
      59              21 : StrEquivalent(const PRUnichar *a, const PRUnichar *b)
      60                 : {
      61                 :     static const PRUnichar emptyStr[] = {0};
      62                 : 
      63              21 :     if (!a)
      64               0 :         a = emptyStr;
      65              21 :     if (!b)
      66               0 :         b = emptyStr;
      67                 : 
      68              21 :     return nsCRT::strcmp(a, b) == 0;
      69                 : }
      70                 : 
      71                 : //-----------------------------------------------------------------------------
      72                 : // nsHttpAuthCache <public>
      73                 : //-----------------------------------------------------------------------------
      74                 : 
      75             679 : nsHttpAuthCache::nsHttpAuthCache()
      76             679 :     : mDB(nsnull)
      77                 : {
      78             679 : }
      79                 : 
      80             677 : nsHttpAuthCache::~nsHttpAuthCache()
      81                 : {
      82             677 :     if (mDB)
      83               0 :         ClearAll();
      84             677 : }
      85                 : 
      86                 : nsresult
      87             693 : nsHttpAuthCache::Init()
      88                 : {
      89             693 :     NS_ENSURE_TRUE(!mDB, NS_ERROR_ALREADY_INITIALIZED);
      90                 : 
      91             693 :     LOG(("nsHttpAuthCache::Init\n"));
      92                 : 
      93                 :     mDB = PL_NewHashTable(128, (PLHashFunction) PL_HashString,
      94                 :                                (PLHashComparator) PL_CompareStrings,
      95             693 :                                (PLHashComparator) 0, &gHashAllocOps, this);
      96             693 :     if (!mDB)
      97               0 :         return NS_ERROR_OUT_OF_MEMORY;
      98                 : 
      99             693 :     return NS_OK;
     100                 : }
     101                 : 
     102                 : nsresult
     103            3494 : nsHttpAuthCache::GetAuthEntryForPath(const char *scheme,
     104                 :                                      const char *host,
     105                 :                                      PRInt32     port,
     106                 :                                      const char *path,
     107                 :                                      nsHttpAuthEntry **entry)
     108                 : {
     109            3494 :     LOG(("nsHttpAuthCache::GetAuthEntryForPath [key=%s://%s:%d path=%s]\n",
     110                 :         scheme, host, port, path));
     111                 : 
     112            6988 :     nsCAutoString key;
     113            3494 :     nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
     114            3494 :     if (!node)
     115            3487 :         return NS_ERROR_NOT_AVAILABLE;
     116                 : 
     117               7 :     *entry = node->LookupEntryByPath(path);
     118               7 :     return *entry ? NS_OK : NS_ERROR_NOT_AVAILABLE;
     119                 : }
     120                 : 
     121                 : nsresult
     122              64 : nsHttpAuthCache::GetAuthEntryForDomain(const char *scheme,
     123                 :                                        const char *host,
     124                 :                                        PRInt32     port,
     125                 :                                        const char *realm,
     126                 :                                        nsHttpAuthEntry **entry)
     127                 : 
     128                 : {
     129              64 :     LOG(("nsHttpAuthCache::GetAuthEntryForDomain [key=%s://%s:%d realm=%s]\n",
     130                 :         scheme, host, port, realm));
     131                 : 
     132             128 :     nsCAutoString key;
     133              64 :     nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
     134              64 :     if (!node)
     135              53 :         return NS_ERROR_NOT_AVAILABLE;
     136                 : 
     137              11 :     *entry = node->LookupEntryByRealm(realm);
     138              11 :     return *entry ? NS_OK : NS_ERROR_NOT_AVAILABLE;
     139                 : }
     140                 : 
     141                 : nsresult
     142              27 : nsHttpAuthCache::SetAuthEntry(const char *scheme,
     143                 :                               const char *host,
     144                 :                               PRInt32     port,
     145                 :                               const char *path,
     146                 :                               const char *realm,
     147                 :                               const char *creds,
     148                 :                               const char *challenge,
     149                 :                               const nsHttpAuthIdentity *ident,
     150                 :                               nsISupports *metadata)
     151                 : {
     152                 :     nsresult rv;
     153                 : 
     154              27 :     LOG(("nsHttpAuthCache::SetAuthEntry [key=%s://%s:%d realm=%s path=%s metadata=%x]\n",
     155                 :         scheme, host, port, realm, path, metadata));
     156                 : 
     157              27 :     if (!mDB) {
     158              14 :         rv = Init();
     159              14 :         if (NS_FAILED(rv)) return rv;
     160                 :     }
     161                 : 
     162              54 :     nsCAutoString key;
     163              27 :     nsHttpAuthNode *node = LookupAuthNode(scheme, host, port, key);
     164                 : 
     165              27 :     if (!node) {
     166                 :         // create a new entry node and set the given entry
     167              27 :         node = new nsHttpAuthNode();
     168              27 :         if (!node)
     169               0 :             return NS_ERROR_OUT_OF_MEMORY;
     170              27 :         rv = node->SetAuthEntry(path, realm, creds, challenge, ident, metadata);
     171              27 :         if (NS_FAILED(rv))
     172               0 :             delete node;
     173                 :         else
     174              27 :             PL_HashTableAdd(mDB, nsCRT::strdup(key.get()), node);
     175              27 :         return rv;
     176                 :     }
     177                 : 
     178               0 :     return node->SetAuthEntry(path, realm, creds, challenge, ident, metadata);
     179                 : }
     180                 : 
     181                 : void
     182               7 : nsHttpAuthCache::ClearAuthEntry(const char *scheme,
     183                 :                                 const char *host,
     184                 :                                 PRInt32     port,
     185                 :                                 const char *realm)
     186                 : {
     187               7 :     if (!mDB)
     188               0 :         return;
     189                 : 
     190              14 :     nsCAutoString key;
     191               7 :     GetAuthKey(scheme, host, port, key);
     192               7 :     PL_HashTableRemove(mDB, key.get());
     193                 : }
     194                 : 
     195                 : nsresult
     196            1370 : nsHttpAuthCache::ClearAll()
     197                 : {
     198            1370 :     LOG(("nsHttpAuthCache::ClearAll\n"));
     199                 : 
     200            1370 :     if (mDB) {
     201             693 :         PL_HashTableDestroy(mDB);
     202             693 :         mDB = 0;
     203                 :     }
     204            1370 :     return NS_OK;
     205                 : }
     206                 : 
     207                 : //-----------------------------------------------------------------------------
     208                 : // nsHttpAuthCache <private>
     209                 : //-----------------------------------------------------------------------------
     210                 : 
     211                 : nsHttpAuthNode *
     212            3585 : nsHttpAuthCache::LookupAuthNode(const char *scheme,
     213                 :                                 const char *host,
     214                 :                                 PRInt32     port,
     215                 :                                 nsCString  &key)
     216                 : {
     217            3585 :     if (!mDB)
     218              55 :         return nsnull;
     219                 : 
     220            3530 :     GetAuthKey(scheme, host, port, key);
     221                 : 
     222            3530 :     return (nsHttpAuthNode *) PL_HashTableLookup(mDB, key.get());
     223                 : }
     224                 : 
     225                 : void *
     226            1393 : nsHttpAuthCache::AllocTable(void *self, PRSize size)
     227                 : {
     228            1393 :     return malloc(size);
     229                 : }
     230                 : 
     231                 : void
     232            1393 : nsHttpAuthCache::FreeTable(void *self, void *item)
     233                 : {
     234            1393 :     free(item);
     235            1393 : }
     236                 : 
     237                 : PLHashEntry *
     238              27 : nsHttpAuthCache::AllocEntry(void *self, const void *key)
     239                 : {
     240              27 :     return (PLHashEntry *) malloc(sizeof(PLHashEntry));
     241                 : }
     242                 : 
     243                 : void
     244              27 : nsHttpAuthCache::FreeEntry(void *self, PLHashEntry *he, PRUintn flag)
     245                 : {
     246              27 :     if (flag == HT_FREE_VALUE) {
     247                 :         // this would only happen if PL_HashTableAdd were to replace an
     248                 :         // existing entry in the hash table, but we _always_ do a lookup
     249                 :         // before adding a new entry to avoid this case.
     250               0 :         NS_NOTREACHED("should never happen");
     251                 :     }
     252              27 :     else if (flag == HT_FREE_ENTRY) {
     253                 :         // three wonderful flavors of freeing memory ;-)
     254              27 :         delete (nsHttpAuthNode *) he->value;
     255              27 :         nsCRT::free((char *) he->key);
     256              27 :         free(he);
     257                 :     }
     258              27 : }
     259                 : 
     260                 : PLHashAllocOps nsHttpAuthCache::gHashAllocOps =
     261                 : {
     262                 :     nsHttpAuthCache::AllocTable,
     263                 :     nsHttpAuthCache::FreeTable,
     264                 :     nsHttpAuthCache::AllocEntry,
     265                 :     nsHttpAuthCache::FreeEntry
     266                 : };
     267                 : 
     268                 : //-----------------------------------------------------------------------------
     269                 : // nsHttpAuthIdentity
     270                 : //-----------------------------------------------------------------------------
     271                 : 
     272                 : nsresult
     273              63 : nsHttpAuthIdentity::Set(const PRUnichar *domain,
     274                 :                         const PRUnichar *user,
     275                 :                         const PRUnichar *pass)
     276                 : {
     277                 :     PRUnichar *newUser, *newPass, *newDomain;
     278                 : 
     279              63 :     int domainLen = domain ? nsCRT::strlen(domain) : 0;
     280              63 :     int userLen   = user   ? nsCRT::strlen(user)   : 0;
     281              63 :     int passLen   = pass   ? nsCRT::strlen(pass)   : 0; 
     282                 : 
     283              63 :     int len = userLen + 1 + passLen + 1 + domainLen + 1;
     284              63 :     newUser = (PRUnichar *) malloc(len * sizeof(PRUnichar));
     285              63 :     if (!newUser)
     286               0 :         return NS_ERROR_OUT_OF_MEMORY;
     287                 : 
     288              63 :     if (user)
     289              63 :         memcpy(newUser, user, userLen * sizeof(PRUnichar));
     290              63 :     newUser[userLen] = 0;
     291                 : 
     292              63 :     newPass = &newUser[userLen + 1];
     293              63 :     if (pass)
     294              63 :         memcpy(newPass, pass, passLen * sizeof(PRUnichar));
     295              63 :     newPass[passLen] = 0;
     296                 : 
     297              63 :     newDomain = &newPass[passLen + 1];
     298              63 :     if (domain)
     299              61 :         memcpy(newDomain, domain, domainLen * sizeof(PRUnichar));
     300              63 :     newDomain[domainLen] = 0;
     301                 : 
     302                 :     // wait until the end to clear member vars in case input params
     303                 :     // reference our members!
     304              63 :     if (mUser)
     305               0 :         free(mUser);
     306              63 :     mUser = newUser;
     307              63 :     mPass = newPass;
     308              63 :     mDomain = newDomain;
     309              63 :     return NS_OK;
     310                 : }
     311                 : 
     312                 : void
     313            6552 : nsHttpAuthIdentity::Clear()
     314                 : {
     315            6552 :     if (mUser) {
     316              63 :         free(mUser);
     317              63 :         mUser = nsnull;
     318              63 :         mPass = nsnull;
     319              63 :         mDomain = nsnull;
     320                 :     }
     321            6552 : }
     322                 : 
     323                 : bool
     324               7 : nsHttpAuthIdentity::Equals(const nsHttpAuthIdentity &ident) const
     325                 : {
     326                 :     // we could probably optimize this with a single loop, but why bother?
     327               7 :     return StrEquivalent(mUser, ident.mUser) &&
     328               7 :            StrEquivalent(mPass, ident.mPass) &&
     329              14 :            StrEquivalent(mDomain, ident.mDomain);
     330                 : }
     331                 : 
     332                 : //-----------------------------------------------------------------------------
     333                 : // nsHttpAuthEntry
     334                 : //-----------------------------------------------------------------------------
     335                 : 
     336              54 : nsHttpAuthEntry::~nsHttpAuthEntry()
     337                 : {
     338              27 :     if (mRealm)
     339              27 :         free(mRealm);
     340                 : 
     341              81 :     while (mRoot) {
     342              27 :         nsHttpAuthPath *ap = mRoot;
     343              27 :         mRoot = mRoot->mNext;
     344              27 :         free(ap);
     345                 :     }
     346              27 : }
     347                 : 
     348                 : nsresult
     349              27 : nsHttpAuthEntry::AddPath(const char *aPath)
     350                 : {
     351                 :     // null path matches empty path
     352              27 :     if (!aPath)
     353               0 :         aPath = "";
     354                 : 
     355              27 :     nsHttpAuthPath *tempPtr = mRoot;
     356              54 :     while (tempPtr) {
     357               0 :         const char *curpath = tempPtr->mPath;
     358               0 :         if (strncmp(aPath, curpath, nsCRT::strlen(curpath)) == 0)
     359               0 :             return NS_OK; // subpath already exists in the list
     360                 : 
     361               0 :         tempPtr = tempPtr->mNext;
     362                 : 
     363                 :     }
     364                 :     
     365                 :     //Append the aPath
     366                 :     nsHttpAuthPath *newAuthPath;
     367              27 :     int newpathLen = nsCRT::strlen(aPath);
     368              27 :     newAuthPath = (nsHttpAuthPath *) malloc(sizeof(nsHttpAuthPath) + newpathLen);
     369              27 :     if (!newAuthPath)
     370               0 :         return NS_ERROR_OUT_OF_MEMORY;
     371                 : 
     372              27 :     memcpy(newAuthPath->mPath, aPath, newpathLen+1);
     373              27 :     newAuthPath->mNext = nsnull;
     374                 : 
     375              27 :     if (!mRoot)
     376              27 :         mRoot = newAuthPath; //first entry
     377                 :     else
     378               0 :         mTail->mNext = newAuthPath; // Append newAuthPath
     379                 : 
     380                 :     //update the tail pointer.
     381              27 :     mTail = newAuthPath;
     382              27 :     return NS_OK;
     383                 : }
     384                 : 
     385                 : nsresult
     386              27 : nsHttpAuthEntry::Set(const char *path,
     387                 :                      const char *realm,
     388                 :                      const char *creds,
     389                 :                      const char *chall,
     390                 :                      const nsHttpAuthIdentity *ident,
     391                 :                      nsISupports *metadata)
     392                 : {
     393                 :     char *newRealm, *newCreds, *newChall;
     394                 : 
     395              27 :     int realmLen = realm ? nsCRT::strlen(realm) : 0;
     396              27 :     int credsLen = creds ? nsCRT::strlen(creds) : 0;
     397              27 :     int challLen = chall ? nsCRT::strlen(chall) : 0;
     398                 : 
     399              27 :     int len = realmLen + 1 + credsLen + 1 + challLen + 1;
     400              27 :     newRealm = (char *) malloc(len);
     401              27 :     if (!newRealm)
     402               0 :         return NS_ERROR_OUT_OF_MEMORY;
     403                 : 
     404              27 :     if (realm)
     405              27 :         memcpy(newRealm, realm, realmLen);
     406              27 :     newRealm[realmLen] = 0;
     407                 : 
     408              27 :     newCreds = &newRealm[realmLen + 1];
     409              27 :     if (creds)
     410              22 :         memcpy(newCreds, creds, credsLen);
     411              27 :     newCreds[credsLen] = 0;
     412                 : 
     413              27 :     newChall = &newCreds[credsLen + 1];
     414              27 :     if (chall)
     415              23 :         memcpy(newChall, chall, challLen);
     416              27 :     newChall[challLen] = 0;
     417                 : 
     418              27 :     nsresult rv = NS_OK;
     419              27 :     if (ident) {
     420              27 :         rv = mIdent.Set(*ident);
     421                 :     } 
     422               0 :     else if (mIdent.IsEmpty()) {
     423                 :         // If we are not given an identity and our cached identity has not been
     424                 :         // initialized yet (so is currently empty), initialize it now by
     425                 :         // filling it with nulls.  We need to do that because consumers expect
     426                 :         // that mIdent is initialized after this function returns.
     427               0 :         rv = mIdent.Set(nsnull, nsnull, nsnull);
     428                 :     }
     429              27 :     if (NS_FAILED(rv)) {
     430               0 :         free(newRealm);
     431               0 :         return rv;
     432                 :     }
     433                 : 
     434              27 :     rv = AddPath(path);
     435              27 :     if (NS_FAILED(rv)) {
     436               0 :         free(newRealm);
     437               0 :         return rv;
     438                 :     }
     439                 : 
     440                 :     // wait until the end to clear member vars in case input params
     441                 :     // reference our members!
     442              27 :     if (mRealm)
     443               0 :         free(mRealm);
     444                 : 
     445              27 :     mRealm = newRealm;
     446              27 :     mCreds = newCreds;
     447              27 :     mChallenge = newChall;
     448              27 :     mMetaData = metadata;
     449                 : 
     450              27 :     return NS_OK;
     451                 : }
     452                 : 
     453                 : //-----------------------------------------------------------------------------
     454                 : // nsHttpAuthNode
     455                 : //-----------------------------------------------------------------------------
     456                 : 
     457              27 : nsHttpAuthNode::nsHttpAuthNode()
     458                 : {
     459              27 :     LOG(("Creating nsHttpAuthNode @%x\n", this));
     460              27 : }
     461                 : 
     462              54 : nsHttpAuthNode::~nsHttpAuthNode()
     463                 : {
     464              27 :     LOG(("Destroying nsHttpAuthNode @%x\n", this));
     465                 : 
     466              27 :     mList.Clear();
     467              27 : }
     468                 : 
     469                 : nsHttpAuthEntry *
     470               7 : nsHttpAuthNode::LookupEntryByPath(const char *path)
     471                 : {
     472                 :     nsHttpAuthEntry *entry;
     473                 : 
     474                 :     // null path matches empty path
     475               7 :     if (!path)
     476               0 :         path = "";
     477                 : 
     478                 :     // look for an entry that either matches or contains this directory.
     479                 :     // ie. we'll give out credentials if the given directory is a sub-
     480                 :     // directory of an existing entry.
     481               7 :     for (PRUint32 i=0; i<mList.Length(); ++i) {
     482               7 :         entry = mList[i];
     483               7 :         nsHttpAuthPath *authPath = entry->RootPath();
     484              14 :         while (authPath) {
     485               7 :             const char *entryPath = authPath->mPath;
     486                 :             // proxy auth entries have no path, so require exact match on
     487                 :             // empty path string.
     488               7 :             if (entryPath[0] == '\0') {
     489               0 :                 if (path[0] == '\0')
     490               0 :                     return entry;
     491                 :             }
     492               7 :             else if (strncmp(path, entryPath, nsCRT::strlen(entryPath)) == 0)
     493               7 :                 return entry;
     494                 : 
     495               0 :             authPath = authPath->mNext;
     496                 :         }
     497                 :     }
     498               0 :     return nsnull;
     499                 : }
     500                 : 
     501                 : nsHttpAuthEntry *
     502              38 : nsHttpAuthNode::LookupEntryByRealm(const char *realm)
     503                 : {
     504                 :     nsHttpAuthEntry *entry;
     505                 : 
     506                 :     // null realm matches empty realm
     507              38 :     if (!realm)
     508               0 :         realm = "";
     509                 : 
     510                 :     // look for an entry that matches this realm
     511                 :     PRUint32 i;
     512              38 :     for (i=0; i<mList.Length(); ++i) {
     513              11 :         entry = mList[i];
     514              11 :         if (strcmp(realm, entry->Realm()) == 0)
     515              11 :             return entry;
     516                 :     }
     517              27 :     return nsnull;
     518                 : }
     519                 : 
     520                 : nsresult
     521              27 : nsHttpAuthNode::SetAuthEntry(const char *path,
     522                 :                              const char *realm,
     523                 :                              const char *creds,
     524                 :                              const char *challenge,
     525                 :                              const nsHttpAuthIdentity *ident,
     526                 :                              nsISupports *metadata)
     527                 : {
     528                 :     // look for an entry with a matching realm
     529              27 :     nsHttpAuthEntry *entry = LookupEntryByRealm(realm);
     530              27 :     if (!entry) {
     531              27 :         entry = new nsHttpAuthEntry(path, realm, creds, challenge, ident, metadata);
     532              27 :         if (!entry)
     533               0 :             return NS_ERROR_OUT_OF_MEMORY;
     534              27 :         mList.AppendElement(entry);
     535                 :     }
     536                 :     else {
     537                 :         // update the entry...
     538               0 :         entry->Set(path, realm, creds, challenge, ident, metadata);
     539                 :     }
     540                 : 
     541              27 :     return NS_OK;
     542                 : }
     543                 : 
     544                 : void
     545               0 : nsHttpAuthNode::ClearAuthEntry(const char *realm)
     546                 : {
     547               0 :     nsHttpAuthEntry *entry = LookupEntryByRealm(realm);
     548               0 :     if (entry) {
     549               0 :         mList.RemoveElement(entry); // double search OK
     550                 :     }
     551               0 : }

Generated by: LCOV version 1.7