--- mozilla/netwerk/build/Makefile.in Wed Apr 10 05:13:50 2002 +++ /home/kouril/soft-local/mozilla/netwerk/build/Makefile.in Mon Jun 24 16:14:51 2002 @@ -62,6 +62,13 @@ $(DIST)/lib/$(LIB_PREFIX)nkres_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)nkabout_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)nkkwd_s.$(LIB_SUFFIX) \ + /usr/heimdal/lib/libgssapi.a \ + /usr/heimdal/lib/libkrb5.a \ + /usr/heimdal/lib/libasn1.a \ + /usr/heimdal/lib/libroken.a \ + /usr/lib/libdb.a \ + /usr/lib/libresolv.a \ + /software/openssl-0.9.6/lib/libcrypto.a \ $(NULL) LOCAL_INCLUDES = \ --- mozilla/netwerk/protocol/http/src/Makefile.in Wed May 1 03:20:13 2002 +++ /home/kouril/soft-local/mozilla/netwerk/protocol/http/src/Makefile.in Mon Jun 10 11:30:16 2002 @@ -53,10 +53,11 @@ nsHttpAuthCache.cpp \ nsHttpBasicAuth.cpp \ nsHttpDigestAuth.cpp \ + nsHttpGssapiAuth.cpp \ nsHttpPipeline.cpp \ $(NULL) -LOCAL_INCLUDES=-I$(srcdir)/../../../streamconv/converters +LOCAL_INCLUDES=-I$(srcdir)/../../../streamconv/converters -I/usr/heimdal/include # we don't want the shared lib, but we want to force the creation of a # static lib. @@ -64,7 +65,7 @@ include $(topsrcdir)/config/rules.mk -DEFINES += -D_IMPL_NS_NET +DEFINES += -D_IMPL_NS_NET -DGSSAPI ifeq ($(OS_ARCH),WINNT) DEFINES += -DWIN32_LEAN_AND_MEAN endif --- mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp Thu May 9 08:43:49 2002 +++ /home/kouril/soft-local/mozilla/netwerk/protocol/http/src/nsHttpChannel.cpp Mon Jun 24 16:18:17 2002 @@ -50,6 +50,10 @@ static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID); +#ifdef GSSAPI +#include "nsHttpGssapiAuth.h" +#endif + //----------------------------------------------------------------------------- // nsHttpChannel //----------------------------------------------------------------------------- @@ -1561,6 +1565,9 @@ const char *challenge; PRBool proxyAuth = (httpStatus == 407); + nsCAutoString creds; + const char *p; + nsresult rv; if (proxyAuth) challenge = mResponseHead->PeekHeader(nsHttp::Proxy_Authenticate); @@ -1574,9 +1581,18 @@ LOG(("challenge=%s\n", challenge)); - nsCAutoString creds; - nsresult rv = GetCredentials(challenge, proxyAuth, creds); - if (NS_FAILED(rv)) return rv; + p = challenge; + do { + LOG(("Trying %s\n", p)); + rv = GetCredentials(p, proxyAuth, creds); + if (NS_SUCCEEDED(rv)) break; + + p = strchr(p, '\n'); + /* mela by se spise vyhodit opravdu pouzita metoda. */ + if (p == NULL) return NS_ERROR_UNEXPECTED; + p++; + } while (NS_FAILED(rv)); + // set the authentication credentials if (proxyAuth) @@ -1642,6 +1658,61 @@ nsCAutoString challenge; nsCOMPtr auth; + nsHttpAuthEntry *entry = nsnull; + + const char *host; + nsCAutoString path; + nsXPIDLString *user; + nsXPIDLString *pass; + PRInt32 port; + + if (proxyAuth) { + host = mConnectionInfo->ProxyHost(); + port = mConnectionInfo->ProxyPort(); + user = &mProxyUser; + pass = &mProxyPass; + } + else { + host = mConnectionInfo->Host(); + port = mConnectionInfo->Port(); + user = &mUser; + pass = &mPass; + + rv = GetCurrentPath(path); + if (NS_FAILED(rv)) return rv; + } + +#ifdef GSSAPI + authCache->GetAuthEntryForPath(host, port, path.get(), &entry); + if (entry && entry->Pass() == NULL) { + /* some authentication method was alredy tryied and was not sucessful + (since we are again here). Suppose it was Negotiate and remove it + from the list of available methods so that another method can have + a chance too. */ + /* do entry by se mozna dal ulozit seznam metod, ktere se jiz pouzily. + */ + char *p, *q; + p = strstr(challenges, "GSS-Negotiate"); /* tolower() */ + if (p != NULL) { + LOG(("Removing Negotiate from challenges (%s)\n", challenges)); + q = strchr(p, '\n'); + if (q == NULL) { + /* the negotiate method is last in the list so we can just put an + ending zero. */ + if (p > challenges) + p--; + *p = '\0'; + } + else { + q++; + while (*q) *p++ = *q++; + *p = '\0'; + } + LOG(("challenges=%s\n", challenges)); + } + } +#endif + rv = SelectChallenge(challenges, challenge, getter_AddRefs(auth)); if (!auth) { @@ -1653,6 +1724,7 @@ rv = ParseRealm(challenge.get(), realm); if (NS_FAILED(rv)) return rv; +#if 0 const char *host; nsCAutoString path; nsXPIDLString *user; @@ -1674,6 +1746,7 @@ rv = GetCurrentPath(path); if (NS_FAILED(rv)) return rv; } +#endif // // if we already tried some credentials for this transaction, then @@ -1681,9 +1754,17 @@ // in the cache have changed, in which case we'd want to give them a // try instead. // - nsHttpAuthEntry *entry = nsnull; - authCache->GetAuthEntryForDomain(host, port, realm.get(), &entry); +#ifdef GSSAPI + if (PL_strncasecmp(challenge.get(), "GSS-Negotiate", 9) == 0) + authCache->GetAuthEntryForPath(host, port, path.get(), &entry); + else +#endif + authCache->GetAuthEntryForDomain(host, port, realm.get(), &entry); if (entry) { +#ifdef GSSAPI + /* hesla nejsou pouzivana pro GSSAPI autentizaci */ + if (PL_strncasecmp(challenge.get(), "GSS-Negotiate", 9) != 0) +#endif if (user->Equals(entry->User()) && pass->Equals(entry->Pass())) { LOG(("clearing bad credentials from the auth cache\n")); // ok, we've already tried this user:pass combo, so clear the @@ -1708,12 +1789,19 @@ } if (!entry && user->IsEmpty()) { - // at this point we are forced to interact with the user to get their - // username and password for this domain. - rv = PromptForUserPass(host, port, proxyAuth, realm.get(), - getter_Copies(*user), - getter_Copies(*pass)); - if (NS_FAILED(rv)) return rv; +#ifdef GSSAPI + /* pro kerbera predpokladame, ze se pouziji listky z disku. Neni proto + * potreba ptat se uzivatele na heslo. */ + if (PL_strncasecmp(challenge.get(), "GSS-Negotiate", 9) != 0) +#endif + { + // at this point we are forced to interact with the user to get their + // username and password for this domain. + rv = PromptForUserPass(host, port, proxyAuth, realm.get(), + getter_Copies(*user), + getter_Copies(*pass)); + if (NS_FAILED(rv)) return rv; + } } // ask the auth cache for a container for any meta data it might want to @@ -1794,6 +1882,17 @@ nsresult rv; nsCOMPtr serv = do_GetService(contractid.get(), &rv); +#ifdef GSSAPI + if (NS_FAILED(rv)) { + if (PL_strncasecmp(scheme, "GSS-Negotiate", 14) == 0) { + /* LS: zatim nevim jak donutit do_GetService() aby pracoval s mym + * nsHttpGssapiAuth objektem. Objekt proto vytvarim rucne zde */ + *auth = :: new nsHttpGssapiAuth(); + NS_ADDREF(*auth); + return NS_OK; + } + } +#endif if (NS_FAILED(rv)) return rv; *auth = serv; --- mozilla/netwerk/protocol/http/src/nsHttpGssapiAuth.cpp Mon Jun 24 16:11:42 2002 +++ /home/kouril/soft-local/mozilla/netwerk/protocol/http/src/nsHttpGssapiAuth.cpp Fri Jun 21 10:58:31 2002 @@ -0,0 +1,174 @@ +#include +#include "nsHttp.h" +#include "nsHttpGssapiAuth.h" +#include "nsIHttpChannel.h" +#include "nsIServiceManager.h" +#include "nsISupportsPrimitives.h" +#include "nsIURI.h" +#include "nsString.h" +#include "nsReadableUtils.h" +#include "plbase64.h" +#include "plstr.h" +#include "prprf.h" +#include "prmem.h" + +#include + +nsHttpGssapiAuth::nsHttpGssapiAuth() +{ + LOG(("nsHttpGssapiAuth::nsHttpGssapiAuth()\n")); + NS_INIT_ISUPPORTS(); +} + +nsHttpGssapiAuth::~nsHttpGssapiAuth() +{ + LOG(("nsHttpGssapiAuth::~nsHttpGssapiAuth()\n")); +} + +//----------------------------------------------------------------------------- +// nsHttpGssapiAuth::nsISupports +//----------------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS1(nsHttpGssapiAuth, nsIHttpAuthenticator); + +//----------------------------------------------------------------------------- +// nsHttpGssapiAuth::nsIHttpAuthenticator +//----------------------------------------------------------------------------- + +char * +nsHttpGssapiAuth::GetGssError(int min_stat, char *prefix) +{ + /* Opsano z heimdalu (appl/test/gss_common.c) */ + OM_uint32 new_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc status_string; + OM_uint32 ret; + nsCAutoString str(prefix); + + str += ": "; + do { + ret = gss_display_status (&new_stat, + min_stat, + GSS_C_MECH_CODE, + GSS_C_NO_OID, + &msg_ctx, + &status_string); + str += (char *)status_string.value; + str += "\n"; + gss_release_buffer (&new_stat, &status_string); + } while (!GSS_ERROR(ret) && msg_ctx != 0); + + return ToNewCString(str); //nemelo by se nekde uvolnit ?? +} + +NS_IMETHODIMP +nsHttpGssapiAuth::GenerateCredentials(nsIHttpChannel *httpChannel, + const char *challenge, + const PRUnichar *username, + const PRUnichar *password, + nsISupports *extra, + char **creds) +{ + OM_uint32 major_status, minor_status; + gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_name_t server; + char server_name[1024]; + + nsCOMPtr uri; + nsresult rv; + nsCAutoString hostname; + + LOG(("nsHttpGssapiAuth::GenerateCredentials() [challenge=%s]\n", challenge)); + + NS_ENSURE_ARG_POINTER(creds); + + PRBool isGssapiAuth = !PL_strncasecmp(challenge, "GSS-Negotiate", 9); + NS_ENSURE_TRUE(isGssapiAuth, NS_ERROR_UNEXPECTED); + + rv = httpChannel->GetURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) return rv; + + rv = uri->GetAsciiHost(hostname); + if (NS_FAILED(rv)) return rv; + + /* resolv() host na FQDN */ + LOG(("nsHttpGssapiAuth::GenerateCredentials() : hostname = %s\n", + hostname.get())); + + PR_snprintf(server_name, sizeof(server_name), "khttp@%s", hostname.get()); + input_token.value = server_name; + input_token.length = strlen(server_name) + 1; + major_status = gss_import_name(&minor_status, + &input_token, + GSS_C_NT_HOSTBASED_SERVICE, + &server); + if (GSS_ERROR(major_status)) { + LOG(("%s", GetGssError(minor_status, "Chyba v gss_import_name()"))); + return NS_ERROR_FAILURE; // nejaka lepsi chyba ?? + } + + /* XXX if challenge contains a token convert it to input_token */ + input_token.length = 0; + input_token.value = NULL; + + major_status = gss_init_sec_context(&minor_status, + GSS_C_NO_CREDENTIAL, + &gss_context, + server, + GSS_C_NO_OID, + GSS_C_DELEG_FLAG, + 0, + GSS_C_NO_CHANNEL_BINDINGS, + &input_token, + NULL, + &output_token, + NULL, + NULL); + if (GSS_ERROR(major_status)) { + LOG(("%s", GetGssError(minor_status, "chyba v gss_init_sec_context()"))); + return NS_ERROR_FAILURE; //lepsi kod chyby ??? + } + + if (output_token.length != 0) { + char *encoded_token = PL_Base64Encode((char *)output_token.value, + output_token.length, + nsnull); + if (encoded_token == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + LOG(("Posilam token delky %d\n", output_token.length)); + + // allocate a buffer sizeof("GSS-Negotiate" + " " + b64output_token + "\0") + *creds = (char *) malloc (14 + strlen(encoded_token) + 1); + if (!*creds) + return NS_ERROR_OUT_OF_MEMORY; + + PL_strcpy(*creds, "GSS-Negotiate "); + PL_strcpy(*creds + 14, encoded_token); + + PR_Free(encoded_token); + + gss_release_buffer(&minor_status, &output_token); + } + + /* release context */ + + return NS_OK; +} + +NS_IMETHODIMP +nsHttpGssapiAuth::AreCredentialsReusable(PRBool *result) +{ + LOG(("nsHttpGssapiAuth::AreCredentialsReusable()\n")); + *result = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsHttpGssapiAuth::AllocateMetaData(nsISupports **result) +{ + LOG(("nsHttpGssapiAuth::AllocateMetaData()\n")); + return NS_OK; +} --- mozilla/netwerk/protocol/http/src/nsHttpGssapiAuth.h Mon Jun 24 16:11:42 2002 +++ /home/kouril/soft-local/mozilla/netwerk/protocol/http/src/nsHttpGssapiAuth.h Mon Jun 10 11:28:41 2002 @@ -0,0 +1,21 @@ +#ifndef nsGssapiAuth_h__ +#define nsGssapiAuth_h__ + +#include "nsIHttpAuthenticator.h" + +#include "nsISignatureVerifier.h" +#include "nsString.h" +#include "nsCOMPtr.h" + +class nsHttpGssapiAuth : public nsIHttpAuthenticator +{ + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIHTTPAUTHENTICATOR + + nsHttpGssapiAuth(); + virtual ~nsHttpGssapiAuth(); + private: + char * GetGssError(int status, char *prefix); +}; +#endif /* nsGssapiAuth_h__ */