| File: | root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp |
| Warning: | line 235, column 5 Value stored to 'ret' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* vim:set ts=4 sw=2 sts=2 et cindent: */ |
| 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 | // |
| 7 | // GSSAPI Authentication Support Module |
| 8 | // |
| 9 | // Described by IETF Internet draft: draft-brezak-kerberos-http-00.txt |
| 10 | // (formerly draft-brezak-spnego-http-04.txt) |
| 11 | // |
| 12 | // Also described here: |
| 13 | // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/http-sso-1.asp |
| 14 | // |
| 15 | // |
| 16 | |
| 17 | #include "mozilla/ArrayUtils.h" |
| 18 | #include "mozilla/IntegerPrintfMacros.h" |
| 19 | |
| 20 | #include "nsCOMPtr.h" |
| 21 | #include "nsNativeCharsetUtils.h" |
| 22 | #include "mozilla/Preferences.h" |
| 23 | #include "mozilla/SharedLibrary.h" |
| 24 | #include "mozilla/glean/SecurityManagerSslMetrics.h" |
| 25 | |
| 26 | #include "nsAuthGSSAPI.h" |
| 27 | |
| 28 | #ifdef XP_MACOSX |
| 29 | # include <Kerberos/Kerberos.h> |
| 30 | #endif |
| 31 | |
| 32 | #ifdef XP_MACOSX |
| 33 | typedef KLStatus (*KLCacheHasValidTickets_type)(KLPrincipal, KLKerberosVersion, |
| 34 | KLBoolean*, KLPrincipal*, |
| 35 | char**); |
| 36 | #endif |
| 37 | |
| 38 | #if defined(HAVE_RES_NINIT1) |
| 39 | # include <sys/types.h> |
| 40 | # include <netinet/in.h> |
| 41 | # include <arpa/nameser.h> |
| 42 | # include <resolv.h> |
| 43 | #endif |
| 44 | |
| 45 | using namespace mozilla; |
| 46 | |
| 47 | //----------------------------------------------------------------------------- |
| 48 | |
| 49 | // We define GSS_C_NT_HOSTBASED_SERVICE explicitly since it may be referenced |
| 50 | // by by a different name depending on the implementation of gss but always |
| 51 | // has the same value |
| 52 | |
| 53 | static gss_OID_desc gss_c_nt_hostbased_service = { |
| 54 | 10, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"}; |
| 55 | |
| 56 | static const char kNegotiateAuthGssLib[] = "network.negotiate-auth.gsslib"; |
| 57 | static const char kNegotiateAuthNativeImp[] = |
| 58 | "network.negotiate-auth.using-native-gsslib"; |
| 59 | |
| 60 | static struct GSSFunction { |
| 61 | const char* str; |
| 62 | PRFuncPtr func; |
| 63 | } gssFuncs[] = {{"gss_display_status", nullptr}, |
| 64 | {"gss_init_sec_context", nullptr}, |
| 65 | {"gss_indicate_mechs", nullptr}, |
| 66 | {"gss_release_oid_set", nullptr}, |
| 67 | {"gss_delete_sec_context", nullptr}, |
| 68 | {"gss_import_name", nullptr}, |
| 69 | {"gss_release_buffer", nullptr}, |
| 70 | {"gss_release_name", nullptr}, |
| 71 | {"gss_wrap", nullptr}, |
| 72 | {"gss_unwrap", nullptr}}; |
| 73 | |
| 74 | static bool gssNativeImp = true; |
| 75 | static PRLibrary* gssLibrary = nullptr; |
| 76 | |
| 77 | #define gss_display_status_ptr((gss_display_status_type) * gssFuncs[0].func) ((gss_display_status_type) * gssFuncs[0].func) |
| 78 | #define gss_init_sec_context_ptr((gss_init_sec_context_type) * gssFuncs[1].func) \ |
| 79 | ((gss_init_sec_context_type) * gssFuncs[1].func) |
| 80 | #define gss_indicate_mechs_ptr((gss_indicate_mechs_type) * gssFuncs[2].func) ((gss_indicate_mechs_type) * gssFuncs[2].func) |
| 81 | #define gss_release_oid_set_ptr((gss_release_oid_set_type) * gssFuncs[3].func) ((gss_release_oid_set_type) * gssFuncs[3].func) |
| 82 | #define gss_delete_sec_context_ptr((gss_delete_sec_context_type) * gssFuncs[4].func) \ |
| 83 | ((gss_delete_sec_context_type) * gssFuncs[4].func) |
| 84 | #define gss_import_name_ptr((gss_import_name_type) * gssFuncs[5].func) ((gss_import_name_type) * gssFuncs[5].func) |
| 85 | #define gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func) ((gss_release_buffer_type) * gssFuncs[6].func) |
| 86 | #define gss_release_name_ptr((gss_release_name_type) * gssFuncs[7].func) ((gss_release_name_type) * gssFuncs[7].func) |
| 87 | #define gss_wrap_ptr((gss_wrap_type) * gssFuncs[8].func) ((gss_wrap_type) * gssFuncs[8].func) |
| 88 | #define gss_unwrap_ptr((gss_unwrap_type) * gssFuncs[9].func) ((gss_unwrap_type) * gssFuncs[9].func) |
| 89 | |
| 90 | #ifdef XP_MACOSX |
| 91 | static PRFuncPtr KLCacheHasValidTicketsPtr; |
| 92 | # define KLCacheHasValidTickets_ptr \ |
| 93 | ((KLCacheHasValidTickets_type) * KLCacheHasValidTicketsPtr) |
| 94 | #endif |
| 95 | |
| 96 | static nsresult gssInit() { |
| 97 | #ifdef XP_WIN |
| 98 | nsAutoString libPathU; |
| 99 | Preferences::GetString(kNegotiateAuthGssLib, libPathU); |
| 100 | NS_ConvertUTF16toUTF8 libPath(libPathU); |
| 101 | #else |
| 102 | nsAutoCString libPath; |
| 103 | Preferences::GetCString(kNegotiateAuthGssLib, libPath); |
| 104 | #endif |
| 105 | gssNativeImp = Preferences::GetBool(kNegotiateAuthNativeImp); |
| 106 | |
| 107 | PRLibrary* lib = nullptr; |
| 108 | |
| 109 | if (!libPath.IsEmpty()) { |
| 110 | LOG(("Attempting to load user specified library [%s]\n", libPath.get()))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Attempting to load user specified library [%s]\n" , libPath.get()); } } while (0); |
| 111 | gssNativeImp = false; |
| 112 | #ifdef XP_WIN |
| 113 | lib = LoadLibraryWithFlags(libPathU.get()); |
| 114 | #else |
| 115 | lib = LoadLibraryWithFlags(libPath.get()); |
| 116 | #endif |
| 117 | } else { |
| 118 | #ifdef XP_WIN |
| 119 | # ifdef _WIN64 |
| 120 | constexpr auto kLibName = u"gssapi64.dll"_ns; |
| 121 | # else |
| 122 | constexpr auto kLibName = u"gssapi32.dll"_ns; |
| 123 | # endif |
| 124 | |
| 125 | lib = LoadLibraryWithFlags(kLibName.get()); |
| 126 | #elif defined(__OpenBSD__) |
| 127 | /* OpenBSD doesn't register inter-library dependencies in basesystem |
| 128 | * libs therefor we need to load all the libraries gssapi depends on, |
| 129 | * in the correct order and with LD_GLOBAL for GSSAPI auth to work |
| 130 | * fine. |
| 131 | */ |
| 132 | |
| 133 | const char* const verLibNames[] = { |
| 134 | "libasn1.so", "libcrypto.so", "libroken.so", "libheimbase.so", |
| 135 | "libcom_err.so", "libkrb5.so", "libgssapi.so"}; |
| 136 | |
| 137 | PRLibSpec libSpec; |
| 138 | for (size_t i = 0; i < std::size(verLibNames); ++i) { |
| 139 | libSpec.type = PR_LibSpec_Pathname; |
| 140 | libSpec.value.pathname = verLibNames[i]; |
| 141 | lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_GLOBAL0x4); |
| 142 | } |
| 143 | |
| 144 | #else |
| 145 | |
| 146 | const char* const libNames[] = {"gss", "gssapi_krb5", "gssapi"}; |
| 147 | |
| 148 | const char* const verLibNames[] = { |
| 149 | "libgssapi_krb5.so.2", /* MIT - FC, Suse10, Debian */ |
| 150 | "libgssapi.so.4", /* Heimdal - Suse10, MDK */ |
| 151 | "libgssapi.so.1" /* Heimdal - Suse9, CITI - FC, MDK, Suse10*/ |
| 152 | }; |
| 153 | |
| 154 | for (size_t i = 0; i < std::size(verLibNames) && !lib; ++i) { |
| 155 | lib = PR_LoadLibrary(verLibNames[i]); |
| 156 | |
| 157 | /* The CITI libgssapi library calls exit() during |
| 158 | * initialization if it's not correctly configured. Try to |
| 159 | * ensure that we never use this library for our GSSAPI |
| 160 | * support, as its just a wrapper library, anyway. |
| 161 | * See Bugzilla #325433 |
| 162 | */ |
| 163 | if (lib && PR_FindFunctionSymbol(lib, "internal_krb5_gss_initialize") && |
| 164 | PR_FindFunctionSymbol(lib, "gssd_pname_to_uid")) { |
| 165 | LOG(("CITI libgssapi found, which calls exit(). Skipping\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "CITI libgssapi found, which calls exit(). Skipping\n" ); } } while (0); |
| 166 | PR_UnloadLibrary(lib); |
| 167 | lib = nullptr; |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | for (size_t i = 0; i < std::size(libNames) && !lib; ++i) { |
| 172 | char* libName = PR_GetLibraryName(nullptr, libNames[i]); |
| 173 | if (libName) { |
| 174 | lib = PR_LoadLibrary(libName); |
| 175 | PR_FreeLibraryName(libName); |
| 176 | |
| 177 | if (lib && PR_FindFunctionSymbol(lib, "internal_krb5_gss_initialize") && |
| 178 | PR_FindFunctionSymbol(lib, "gssd_pname_to_uid")) { |
| 179 | LOG(("CITI libgssapi found, which calls exit(). Skipping\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "CITI libgssapi found, which calls exit(). Skipping\n" ); } } while (0); |
| 180 | PR_UnloadLibrary(lib); |
| 181 | lib = nullptr; |
| 182 | } |
| 183 | } |
| 184 | } |
| 185 | #endif |
| 186 | } |
| 187 | |
| 188 | if (!lib) { |
| 189 | LOG(("Fail to load gssapi library\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Fail to load gssapi library\n" ); } } while (0); |
| 190 | return NS_ERROR_FAILURE; |
| 191 | } |
| 192 | |
| 193 | LOG(("Attempting to load gss functions\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Attempting to load gss functions\n" ); } } while (0); |
| 194 | |
| 195 | for (auto& gssFunc : gssFuncs) { |
| 196 | gssFunc.func = PR_FindFunctionSymbol(lib, gssFunc.str); |
| 197 | if (!gssFunc.func) { |
| 198 | LOG(("Fail to load %s function from gssapi library\n", gssFunc.str))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Fail to load %s function from gssapi library\n" , gssFunc.str); } } while (0); |
| 199 | PR_UnloadLibrary(lib); |
| 200 | return NS_ERROR_FAILURE; |
| 201 | } |
| 202 | } |
| 203 | #ifdef XP_MACOSX |
| 204 | if (gssNativeImp && !(KLCacheHasValidTicketsPtr = PR_FindFunctionSymbol( |
| 205 | lib, "KLCacheHasValidTickets"))) { |
| 206 | LOG(("Fail to load KLCacheHasValidTickets function from gssapi library\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Fail to load KLCacheHasValidTickets function from gssapi library\n" ); } } while (0); |
| 207 | PR_UnloadLibrary(lib); |
| 208 | return NS_ERROR_FAILURE; |
| 209 | } |
| 210 | #endif |
| 211 | |
| 212 | gssLibrary = lib; |
| 213 | return NS_OK; |
| 214 | } |
| 215 | |
| 216 | // Generate proper GSSAPI error messages from the major and |
| 217 | // minor status codes. |
| 218 | void LogGssError(OM_uint32 maj_stat, OM_uint32 min_stat, const char* prefix) { |
| 219 | if (!MOZ_LOG_TEST(gNegotiateLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gNegotiateLog, LogLevel::Debug)), 0))) { |
| 220 | return; |
| 221 | } |
| 222 | |
| 223 | OM_uint32 new_stat; |
| 224 | OM_uint32 msg_ctx = 0; |
| 225 | gss_buffer_desc status1_string; |
| 226 | gss_buffer_desc status2_string; |
| 227 | OM_uint32 ret; |
| 228 | nsAutoCString errorStr; |
| 229 | errorStr.Assign(prefix); |
| 230 | |
| 231 | if (!gssLibrary) return; |
| 232 | |
| 233 | errorStr += ": "; |
| 234 | do { |
| 235 | ret = gss_display_status_ptr((gss_display_status_type) * gssFuncs[0].func)(&new_stat, maj_stat, GSS_C_GSS_CODE1, |
Value stored to 'ret' is never read | |
| 236 | GSS_C_NULL_OID((gss_OID)0), &msg_ctx, &status1_string); |
| 237 | errorStr.Append((const char*)status1_string.value, status1_string.length); |
| 238 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&new_stat, &status1_string); |
| 239 | |
| 240 | errorStr += '\n'; |
| 241 | ret = gss_display_status_ptr((gss_display_status_type) * gssFuncs[0].func)(&new_stat, min_stat, GSS_C_MECH_CODE2, |
| 242 | GSS_C_NULL_OID((gss_OID)0), &msg_ctx, &status2_string); |
| 243 | errorStr.Append((const char*)status2_string.value, status2_string.length); |
| 244 | errorStr += '\n'; |
| 245 | } while (!GSS_ERROR(ret)(ret & ((0377ul << 24) | (0377ul << 16))) && msg_ctx != 0); |
| 246 | |
| 247 | LOG(("%s\n", errorStr.get()))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "%s\n", errorStr. get()); } } while (0); |
| 248 | } |
| 249 | |
| 250 | //----------------------------------------------------------------------------- |
| 251 | |
| 252 | nsAuthGSSAPI::nsAuthGSSAPI(pType package) : mServiceFlags(REQ_DEFAULT) { |
| 253 | OM_uint32 minstat; |
| 254 | OM_uint32 majstat; |
| 255 | gss_OID_set mech_set; |
| 256 | gss_OID item; |
| 257 | |
| 258 | unsigned int i; |
| 259 | static gss_OID_desc gss_krb5_mech_oid_desc = { |
| 260 | 9, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; |
| 261 | static gss_OID_desc gss_spnego_mech_oid_desc = { |
| 262 | 6, (void*)"\x2b\x06\x01\x05\x05\x02"}; |
| 263 | |
| 264 | LOG(("entering nsAuthGSSAPI::nsAuthGSSAPI()\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "entering nsAuthGSSAPI::nsAuthGSSAPI()\n" ); } } while (0); |
| 265 | |
| 266 | mComplete = false; |
| 267 | |
| 268 | if (!gssLibrary && NS_FAILED(gssInit())((bool)(__builtin_expect(!!(NS_FAILED_impl(gssInit())), 0)))) return; |
| 269 | |
| 270 | mCtx = GSS_C_NO_CONTEXT((gss_ctx_id_t)0); |
| 271 | mMechOID = &gss_krb5_mech_oid_desc; |
| 272 | |
| 273 | // if the type is kerberos we accept it as default |
| 274 | // and exit |
| 275 | |
| 276 | if (package == PACKAGE_TYPE_KERBEROS) return; |
| 277 | |
| 278 | // Now, look at the list of supported mechanisms, |
| 279 | // if SPNEGO is found, then use it. |
| 280 | // Otherwise, set the desired mechanism to |
| 281 | // GSS_C_NO_OID and let the system try to use |
| 282 | // the default mechanism. |
| 283 | // |
| 284 | // Using Kerberos directly (instead of negotiating |
| 285 | // with SPNEGO) may work in some cases depending |
| 286 | // on how smart the server side is. |
| 287 | |
| 288 | majstat = gss_indicate_mechs_ptr((gss_indicate_mechs_type) * gssFuncs[2].func)(&minstat, &mech_set); |
| 289 | if (GSS_ERROR(majstat)(majstat & ((0377ul << 24) | (0377ul << 16)))) return; |
| 290 | |
| 291 | if (mech_set) { |
| 292 | for (i = 0; i < mech_set->count; i++) { |
| 293 | item = &mech_set->elements[i]; |
| 294 | if (item->length == gss_spnego_mech_oid_desc.length && |
| 295 | !memcmp(item->elements, gss_spnego_mech_oid_desc.elements, |
| 296 | item->length)) { |
| 297 | // ok, we found it |
| 298 | mMechOID = &gss_spnego_mech_oid_desc; |
| 299 | break; |
| 300 | } |
| 301 | } |
| 302 | gss_release_oid_set_ptr((gss_release_oid_set_type) * gssFuncs[3].func)(&minstat, &mech_set); |
| 303 | } |
| 304 | } |
| 305 | |
| 306 | void nsAuthGSSAPI::Reset() { |
| 307 | if (gssLibrary && mCtx != GSS_C_NO_CONTEXT((gss_ctx_id_t)0)) { |
| 308 | OM_uint32 minor_status; |
| 309 | gss_delete_sec_context_ptr((gss_delete_sec_context_type) * gssFuncs[4].func)(&minor_status, &mCtx, GSS_C_NO_BUFFER((gss_buffer_t)0)); |
| 310 | } |
| 311 | mCtx = GSS_C_NO_CONTEXT((gss_ctx_id_t)0); |
| 312 | mComplete = false; |
| 313 | } |
| 314 | |
| 315 | /* static */ |
| 316 | void nsAuthGSSAPI::Shutdown() { |
| 317 | if (gssLibrary) { |
| 318 | PR_UnloadLibrary(gssLibrary); |
| 319 | gssLibrary = nullptr; |
| 320 | } |
| 321 | } |
| 322 | |
| 323 | /* Limitations apply to this class's thread safety. See the header file */ |
| 324 | NS_IMPL_ISUPPORTS(nsAuthGSSAPI, nsIAuthModule)MozExternalRefCountType nsAuthGSSAPI::AddRef(void) { static_assert (!std::is_destructible_v<nsAuthGSSAPI>, "Reference-counted class " "nsAuthGSSAPI" " should not have a public destructor. " "Make this class's destructor non-public" ); do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0" " (" "illegal refcnt" ")", "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0" ") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 324 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsAuthGSSAPI" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("nsAuthGSSAPI" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsAuthGSSAPI\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsAuthGSSAPI\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 324); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("nsAuthGSSAPI" " not thread-safe"); nsrefcnt count = ++mRefCnt ; NS_LogAddRef((this), (count), ("nsAuthGSSAPI"), (uint32_t)( sizeof(*this))); return count; } MozExternalRefCountType nsAuthGSSAPI ::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release" ")", "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0" ") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 324 ); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); do { static_assert( mozilla::detail::AssertionConditionType <decltype("nsAuthGSSAPI" != nullptr)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!("nsAuthGSSAPI" != nullptr))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"nsAuthGSSAPI\" != nullptr" " (" "Must specify a name" ")", "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 324); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsAuthGSSAPI\" != nullptr" ") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null , 324); __attribute__((nomerge)) ::abort(); } while (false); } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership ("nsAuthGSSAPI" " not thread-safe"); const char* const nametmp = "nsAuthGSSAPI"; nsrefcnt count = --mRefCnt; NS_LogRelease( (this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return 0; } return count; } nsresult nsAuthGSSAPI::QueryInterface (const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr )) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!" , "aInstancePtr", "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 324); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE ; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE" ); static const QITableEntry table[] = { {&mozilla::detail ::kImplementedIID<nsAuthGSSAPI, nsIAuthModule>, int32_t ( reinterpret_cast<char*>(static_cast<nsIAuthModule* >((nsAuthGSSAPI*)0x1000)) - reinterpret_cast<char*>( (nsAuthGSSAPI*)0x1000))}, {&mozilla::detail::kImplementedIID <nsAuthGSSAPI, nsISupports>, int32_t(reinterpret_cast< char*>(static_cast<nsISupports*>( static_cast<nsIAuthModule *>((nsAuthGSSAPI*)0x1000))) - reinterpret_cast<char*> ((nsAuthGSSAPI*)0x1000))}, { nullptr, 0 } } ; static_assert(std ::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI (static_cast<void*>(this), aIID, aInstancePtr, table); return rv; } |
| 325 | |
| 326 | NS_IMETHODIMPnsresult |
| 327 | nsAuthGSSAPI::Init(const nsACString& serviceName, uint32_t serviceFlags, |
| 328 | const nsAString& domain, const nsAString& username, |
| 329 | const nsAString& password) { |
| 330 | // we don't expect to be passed any user credentials |
| 331 | NS_ASSERTION(domain.IsEmpty() && username.IsEmpty() && password.IsEmpty(),do { if (!(domain.IsEmpty() && username.IsEmpty() && password.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected credentials" , "domain.IsEmpty() && username.IsEmpty() && password.IsEmpty()" , "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp", 332 ); MOZ_PretendNoReturn(); } } while (0) |
| 332 | "unexpected credentials")do { if (!(domain.IsEmpty() && username.IsEmpty() && password.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected credentials" , "domain.IsEmpty() && username.IsEmpty() && password.IsEmpty()" , "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp", 332 ); MOZ_PretendNoReturn(); } } while (0); |
| 333 | |
| 334 | // it's critial that the caller supply a service name to be used |
| 335 | NS_ENSURE_TRUE(!serviceName.IsEmpty(), NS_ERROR_INVALID_ARG)do { if ((__builtin_expect(!!(!(!serviceName.IsEmpty())), 0)) ) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!serviceName.IsEmpty()" ") failed", nullptr, "/root/firefox-clang/extensions/auth/nsAuthGSSAPI.cpp" , 335); return NS_ERROR_INVALID_ARG; } } while (false); |
| 336 | |
| 337 | LOG(("entering nsAuthGSSAPI::Init()\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "entering nsAuthGSSAPI::Init()\n" ); } } while (0); |
| 338 | |
| 339 | if (!gssLibrary) return NS_ERROR_NOT_INITIALIZED; |
| 340 | |
| 341 | mServiceName = serviceName; |
| 342 | mServiceFlags = serviceFlags; |
| 343 | |
| 344 | static bool sTelemetrySent = false; |
| 345 | if (!sTelemetrySent) { |
| 346 | mozilla::glean::security::ntlm_module_used.AccumulateSingleSample( |
| 347 | serviceFlags & nsIAuthModule::REQ_PROXY_AUTH |
| 348 | ? NTLM_MODULE_KERBEROS_PROXY |
| 349 | : NTLM_MODULE_KERBEROS_DIRECT); |
| 350 | sTelemetrySent = true; |
| 351 | } |
| 352 | |
| 353 | return NS_OK; |
| 354 | } |
| 355 | |
| 356 | NS_IMETHODIMPnsresult |
| 357 | nsAuthGSSAPI::GetNextToken(const void* inToken, uint32_t inTokenLen, |
| 358 | void** outToken, uint32_t* outTokenLen) { |
| 359 | OM_uint32 major_status, minor_status; |
| 360 | OM_uint32 req_flags = 0; |
| 361 | gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER{0, nullptr}; |
| 362 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr}; |
| 363 | gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER((gss_buffer_t)0); |
| 364 | gss_name_t server; |
| 365 | nsAutoCString userbuf; |
| 366 | nsresult rv; |
| 367 | |
| 368 | LOG(("entering nsAuthGSSAPI::GetNextToken()\n"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "entering nsAuthGSSAPI::GetNextToken()\n" ); } } while (0); |
| 369 | |
| 370 | if (!gssLibrary) return NS_ERROR_NOT_INITIALIZED; |
| 371 | |
| 372 | // If they've called us again after we're complete, reset to start afresh. |
| 373 | if (mComplete) Reset(); |
| 374 | |
| 375 | if (mServiceFlags & REQ_DELEGATE) req_flags |= GSS_C_DELEG_FLAG1; |
| 376 | |
| 377 | if (mServiceFlags & REQ_MUTUAL_AUTH) req_flags |= GSS_C_MUTUAL_FLAG2; |
| 378 | |
| 379 | input_token.value = (void*)mServiceName.get(); |
| 380 | input_token.length = mServiceName.Length() + 1; |
| 381 | |
| 382 | #if defined(HAVE_RES_NINIT1) |
| 383 | res_ninit__res_ninit(&_res(*__res_state())); |
| 384 | #endif |
| 385 | major_status = gss_import_name_ptr((gss_import_name_type) * gssFuncs[5].func)(&minor_status, &input_token, |
| 386 | &gss_c_nt_hostbased_service, &server); |
| 387 | input_token.value = nullptr; |
| 388 | input_token.length = 0; |
| 389 | if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16 )))) { |
| 390 | LogGssError(major_status, minor_status, "gss_import_name() failed"); |
| 391 | return NS_ERROR_FAILURE; |
| 392 | } |
| 393 | |
| 394 | if (inToken) { |
| 395 | input_token.length = inTokenLen; |
| 396 | input_token.value = (void*)inToken; |
| 397 | in_token_ptr = &input_token; |
| 398 | } else if (mCtx != GSS_C_NO_CONTEXT((gss_ctx_id_t)0)) { |
| 399 | // If there is no input token, then we are starting a new |
| 400 | // authentication sequence. If we have already initialized our |
| 401 | // security context, then we're in trouble because it means that the |
| 402 | // first sequence failed. We need to bail or else we might end up in |
| 403 | // an infinite loop. |
| 404 | LOG(("Cannot restart authentication sequence!"))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, "Cannot restart authentication sequence!" ); } } while (0); |
| 405 | return NS_ERROR_UNEXPECTED; |
| 406 | } |
| 407 | |
| 408 | #if defined(XP_MACOSX) |
| 409 | // Suppress Kerberos prompts to get credentials. See bug 240643. |
| 410 | // We can only use Mac OS X specific kerb functions if we are using |
| 411 | // the native lib |
| 412 | KLBoolean found; |
| 413 | bool doingMailTask = mServiceName.Find("imap@") || |
| 414 | mServiceName.Find("pop@") || |
| 415 | mServiceName.Find("smtp@") || mServiceName.Find("ldap@"); |
| 416 | |
| 417 | if (!doingMailTask && |
| 418 | (gssNativeImp && |
| 419 | (KLCacheHasValidTickets_ptr(nullptr, kerberosVersion_V5, &found, nullptr, |
| 420 | nullptr) != klNoErr || |
| 421 | !found))) { |
| 422 | major_status = GSS_S_FAILURE(13ul << 16); |
| 423 | minor_status = 0; |
| 424 | } else |
| 425 | #endif /* XP_MACOSX */ |
| 426 | major_status = gss_init_sec_context_ptr((gss_init_sec_context_type) * gssFuncs[1].func)( |
| 427 | &minor_status, GSS_C_NO_CREDENTIAL((gss_cred_id_t)0), &mCtx, server, mMechOID, req_flags, |
| 428 | GSS_C_INDEFINITE0xfffffffful, GSS_C_NO_CHANNEL_BINDINGS((gss_channel_bindings_t)0), in_token_ptr, nullptr, |
| 429 | &output_token, nullptr, nullptr); |
| 430 | |
| 431 | if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16 )))) { |
| 432 | LogGssError(major_status, minor_status, "gss_init_sec_context() failed"); |
| 433 | Reset(); |
| 434 | rv = NS_ERROR_FAILURE; |
| 435 | goto end; |
| 436 | } |
| 437 | if (major_status == GSS_S_COMPLETE0) { |
| 438 | // Mark ourselves as being complete, so that if we're called again |
| 439 | // we know to start afresh. |
| 440 | mComplete = true; |
| 441 | } else if (major_status == GSS_S_CONTINUE_NEEDED(1ul << (0 + 0))) { |
| 442 | // |
| 443 | // The important thing is that we do NOT reset the |
| 444 | // context here because it will be needed on the |
| 445 | // next call. |
| 446 | // |
| 447 | } |
| 448 | |
| 449 | *outTokenLen = output_token.length; |
| 450 | if (output_token.length != 0) { |
| 451 | *outToken = moz_xmemdup(output_token.value, output_token.length); |
| 452 | } else { |
| 453 | *outToken = nullptr; |
| 454 | } |
| 455 | |
| 456 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token); |
| 457 | |
| 458 | if (major_status == GSS_S_COMPLETE0) { |
| 459 | rv = NS_SUCCESS_AUTH_FINISHED; |
| 460 | } else { |
| 461 | rv = NS_OK; |
| 462 | } |
| 463 | |
| 464 | end: |
| 465 | gss_release_name_ptr((gss_release_name_type) * gssFuncs[7].func)(&minor_status, &server); |
| 466 | |
| 467 | LOG((" leaving nsAuthGSSAPI::GetNextToken [rv=%" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, " leaving nsAuthGSSAPI::GetNextToken [rv=%" "x" "]", static_cast<uint32_t>(rv)); } } while (0) |
| 468 | static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = gNegotiateLog ; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module , mozilla::LogLevel::Debug)), 0))) { mozilla::detail::log_print (moz_real_module, mozilla::LogLevel::Debug, " leaving nsAuthGSSAPI::GetNextToken [rv=%" "x" "]", static_cast<uint32_t>(rv)); } } while (0); |
| 469 | return rv; |
| 470 | } |
| 471 | |
| 472 | NS_IMETHODIMPnsresult |
| 473 | nsAuthGSSAPI::Unwrap(const void* inToken, uint32_t inTokenLen, void** outToken, |
| 474 | uint32_t* outTokenLen) { |
| 475 | OM_uint32 major_status, minor_status; |
| 476 | |
| 477 | gss_buffer_desc input_token; |
| 478 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr}; |
| 479 | |
| 480 | input_token.value = (void*)inToken; |
| 481 | input_token.length = inTokenLen; |
| 482 | |
| 483 | major_status = gss_unwrap_ptr((gss_unwrap_type) * gssFuncs[9].func)(&minor_status, mCtx, &input_token, |
| 484 | &output_token, nullptr, nullptr); |
| 485 | if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16 )))) { |
| 486 | LogGssError(major_status, minor_status, "gss_unwrap() failed"); |
| 487 | Reset(); |
| 488 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token); |
| 489 | return NS_ERROR_FAILURE; |
| 490 | } |
| 491 | |
| 492 | *outTokenLen = output_token.length; |
| 493 | |
| 494 | if (output_token.length) { |
| 495 | *outToken = moz_xmemdup(output_token.value, output_token.length); |
| 496 | } else { |
| 497 | *outToken = nullptr; |
| 498 | } |
| 499 | |
| 500 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token); |
| 501 | |
| 502 | return NS_OK; |
| 503 | } |
| 504 | |
| 505 | NS_IMETHODIMPnsresult |
| 506 | nsAuthGSSAPI::Wrap(const void* inToken, uint32_t inTokenLen, bool confidential, |
| 507 | void** outToken, uint32_t* outTokenLen) { |
| 508 | OM_uint32 major_status, minor_status; |
| 509 | |
| 510 | gss_buffer_desc input_token; |
| 511 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr}; |
| 512 | |
| 513 | input_token.value = (void*)inToken; |
| 514 | input_token.length = inTokenLen; |
| 515 | |
| 516 | major_status = |
| 517 | gss_wrap_ptr((gss_wrap_type) * gssFuncs[8].func)(&minor_status, mCtx, confidential, GSS_C_QOP_DEFAULT0, |
| 518 | &input_token, nullptr, &output_token); |
| 519 | |
| 520 | if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16 )))) { |
| 521 | LogGssError(major_status, minor_status, "gss_wrap() failed"); |
| 522 | Reset(); |
| 523 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token); |
| 524 | return NS_ERROR_FAILURE; |
| 525 | } |
| 526 | |
| 527 | *outTokenLen = output_token.length; |
| 528 | |
| 529 | /* it is not possible for output_token.length to be zero */ |
| 530 | *outToken = moz_xmemdup(output_token.value, output_token.length); |
| 531 | gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token); |
| 532 | |
| 533 | return NS_OK; |
| 534 | } |