Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/extensions/auth/./../../../extensions/auth/nsAuthGSSAPI.cpp
Warning:line 232, column 5
Value stored to 'ret' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_extensions_auth0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/extensions/auth -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/extensions/auth -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/extensions/auth -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/extensions/auth -I /root/firefox-clang/netwerk/dns -I /root/firefox-clang/security/manager/ssl -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ Unified_cpp_extensions_auth0.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5//
6// GSSAPI Authentication Support Module
7//
8// Described by IETF Internet draft: draft-brezak-kerberos-http-00.txt
9// (formerly draft-brezak-spnego-http-04.txt)
10//
11// Also described here:
12// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnsecure/html/http-sso-1.asp
13//
14//
15
16#include "mozilla/Atomics.h"
17#include "mozilla/IntegerPrintfMacros.h"
18
19#include "nsCOMPtr.h"
20#include "nsNativeCharsetUtils.h"
21#include "mozilla/Preferences.h"
22#include "mozilla/SharedLibrary.h"
23#include "mozilla/StaticPrefs_network.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
33typedef 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
45using 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
53static gss_OID_desc gss_c_nt_hostbased_service = {
54 10, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"};
55
56static const char kNegotiateAuthGssLib[] = "network.negotiate-auth.gsslib";
57
58static struct GSSFunction {
59 const char* str;
60 PRFuncPtr func;
61} gssFuncs[] = {{"gss_display_status", nullptr},
62 {"gss_init_sec_context", nullptr},
63 {"gss_indicate_mechs", nullptr},
64 {"gss_release_oid_set", nullptr},
65 {"gss_delete_sec_context", nullptr},
66 {"gss_import_name", nullptr},
67 {"gss_release_buffer", nullptr},
68 {"gss_release_name", nullptr},
69 {"gss_wrap", nullptr},
70 {"gss_unwrap", nullptr}};
71
72static PRLibrary* gssLibrary = nullptr;
73
74#define gss_display_status_ptr((gss_display_status_type) * gssFuncs[0].func) ((gss_display_status_type) * gssFuncs[0].func)
75#define gss_init_sec_context_ptr((gss_init_sec_context_type) * gssFuncs[1].func) \
76 ((gss_init_sec_context_type) * gssFuncs[1].func)
77#define gss_indicate_mechs_ptr((gss_indicate_mechs_type) * gssFuncs[2].func) ((gss_indicate_mechs_type) * gssFuncs[2].func)
78#define gss_release_oid_set_ptr((gss_release_oid_set_type) * gssFuncs[3].func) ((gss_release_oid_set_type) * gssFuncs[3].func)
79#define gss_delete_sec_context_ptr((gss_delete_sec_context_type) * gssFuncs[4].func) \
80 ((gss_delete_sec_context_type) * gssFuncs[4].func)
81#define gss_import_name_ptr((gss_import_name_type) * gssFuncs[5].func) ((gss_import_name_type) * gssFuncs[5].func)
82#define gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func) ((gss_release_buffer_type) * gssFuncs[6].func)
83#define gss_release_name_ptr((gss_release_name_type) * gssFuncs[7].func) ((gss_release_name_type) * gssFuncs[7].func)
84#define gss_wrap_ptr((gss_wrap_type) * gssFuncs[8].func) ((gss_wrap_type) * gssFuncs[8].func)
85#define gss_unwrap_ptr((gss_unwrap_type) * gssFuncs[9].func) ((gss_unwrap_type) * gssFuncs[9].func)
86
87#ifdef XP_MACOSX
88static PRFuncPtr KLCacheHasValidTicketsPtr;
89# define KLCacheHasValidTickets_ptr \
90 ((KLCacheHasValidTickets_type) * KLCacheHasValidTicketsPtr)
91#endif
92
93static nsresult gssInit() {
94#ifdef XP_WIN
95 nsAutoString libPathU;
96 Preferences::GetString(kNegotiateAuthGssLib, libPathU);
97 NS_ConvertUTF16toUTF8 libPath(libPathU);
98#else
99 nsAutoCString libPath;
100 Preferences::GetCString(kNegotiateAuthGssLib, libPath);
101#endif
102
103 PRLibrary* lib = nullptr;
104
105 if (!libPath.IsEmpty()) {
106 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)
;
107#ifdef XP_WIN
108 lib = LoadLibraryWithFlags(libPathU.get());
109#else
110 lib = LoadLibraryWithFlags(libPath.get());
111#endif
112 } else {
113#ifdef XP_WIN
114# ifdef _WIN64
115 constexpr auto kLibName = u"gssapi64.dll"_ns;
116# else
117 constexpr auto kLibName = u"gssapi32.dll"_ns;
118# endif
119
120 lib = LoadLibraryWithFlags(kLibName.get());
121#elif defined(__OpenBSD__)
122 /* OpenBSD doesn't register inter-library dependencies in basesystem
123 * libs therefor we need to load all the libraries gssapi depends on,
124 * in the correct order and with LD_GLOBAL for GSSAPI auth to work
125 * fine.
126 */
127
128 const char* const verLibNames[] = {
129 "libasn1.so", "libcrypto.so", "libroken.so", "libheimbase.so",
130 "libcom_err.so", "libkrb5.so", "libgssapi.so"};
131
132 PRLibSpec libSpec;
133 for (size_t i = 0; i < std::size(verLibNames); ++i) {
134 libSpec.type = PR_LibSpec_Pathname;
135 libSpec.value.pathname = verLibNames[i];
136 lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_GLOBAL0x4);
137 }
138
139#else
140
141 const char* const libNames[] = {"gss", "gssapi_krb5", "gssapi"};
142
143 const char* const verLibNames[] = {
144 "libgssapi_krb5.so.2", /* MIT - FC, Suse10, Debian */
145 "libgssapi.so.4", /* Heimdal - Suse10, MDK */
146 "libgssapi.so.1" /* Heimdal - Suse9, CITI - FC, MDK, Suse10*/
147 };
148
149 for (size_t i = 0; i < std::size(verLibNames) && !lib; ++i) {
150 lib = PR_LoadLibrary(verLibNames[i]);
151
152 /* The CITI libgssapi library calls exit() during
153 * initialization if it's not correctly configured. Try to
154 * ensure that we never use this library for our GSSAPI
155 * support, as its just a wrapper library, anyway.
156 * See Bugzilla #325433
157 */
158 if (lib && PR_FindFunctionSymbol(lib, "internal_krb5_gss_initialize") &&
159 PR_FindFunctionSymbol(lib, "gssd_pname_to_uid")) {
160 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)
;
161 PR_UnloadLibrary(lib);
162 lib = nullptr;
163 }
164 }
165
166 for (size_t i = 0; i < std::size(libNames) && !lib; ++i) {
167 char* libName = PR_GetLibraryName(nullptr, libNames[i]);
168 if (libName) {
169 lib = PR_LoadLibrary(libName);
170 PR_FreeLibraryName(libName);
171
172 if (lib && PR_FindFunctionSymbol(lib, "internal_krb5_gss_initialize") &&
173 PR_FindFunctionSymbol(lib, "gssd_pname_to_uid")) {
174 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)
;
175 PR_UnloadLibrary(lib);
176 lib = nullptr;
177 }
178 }
179 }
180#endif
181 }
182
183 if (!lib) {
184 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)
;
185 return NS_ERROR_FAILURE;
186 }
187
188 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)
;
189
190 for (auto& gssFunc : gssFuncs) {
191 gssFunc.func = PR_FindFunctionSymbol(lib, gssFunc.str);
192 if (!gssFunc.func) {
193 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)
;
194 PR_UnloadLibrary(lib);
195 return NS_ERROR_FAILURE;
196 }
197 }
198#ifdef XP_MACOSX
199 if (libPath.IsEmpty() &&
200 StaticPrefs::network_negotiate_auth_using_native_gsslib() &&
201 !(KLCacheHasValidTicketsPtr =
202 PR_FindFunctionSymbol(lib, "KLCacheHasValidTickets"))) {
203 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)
;
204 PR_UnloadLibrary(lib);
205 return NS_ERROR_FAILURE;
206 }
207#endif
208
209 gssLibrary = lib;
210 return NS_OK;
211}
212
213// Generate proper GSSAPI error messages from the major and
214// minor status codes.
215void LogGssError(OM_uint32 maj_stat, OM_uint32 min_stat, const char* prefix) {
216 if (!MOZ_LOG_TEST(gNegotiateLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gNegotiateLog,
LogLevel::Debug)), 0))
) {
217 return;
218 }
219
220 OM_uint32 new_stat;
221 OM_uint32 msg_ctx = 0;
222 gss_buffer_desc status1_string;
223 gss_buffer_desc status2_string;
224 OM_uint32 ret;
225 nsAutoCString errorStr;
226 errorStr.Assign(prefix);
227
228 if (!gssLibrary) return;
229
230 errorStr += ": ";
231 do {
232 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
233 GSS_C_NULL_OID((gss_OID)0), &msg_ctx, &status1_string);
234 errorStr.Append((const char*)status1_string.value, status1_string.length);
235 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&new_stat, &status1_string);
236
237 errorStr += '\n';
238 ret = gss_display_status_ptr((gss_display_status_type) * gssFuncs[0].func)(&new_stat, min_stat, GSS_C_MECH_CODE2,
239 GSS_C_NULL_OID((gss_OID)0), &msg_ctx, &status2_string);
240 errorStr.Append((const char*)status2_string.value, status2_string.length);
241 errorStr += '\n';
242 } while (!GSS_ERROR(ret)(ret & ((0377ul << 24) | (0377ul << 16))) && msg_ctx != 0);
243
244 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)
;
245}
246
247//-----------------------------------------------------------------------------
248
249nsAuthGSSAPI::nsAuthGSSAPI(pType package) : mServiceFlags(REQ_DEFAULT) {
250 OM_uint32 minstat;
251 OM_uint32 majstat;
252 gss_OID_set mech_set;
253 gss_OID item;
254
255 unsigned int i;
256 static gss_OID_desc gss_krb5_mech_oid_desc = {
257 9, (void*)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
258 static gss_OID_desc gss_spnego_mech_oid_desc = {
259 6, (void*)"\x2b\x06\x01\x05\x05\x02"};
260
261 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)
;
262
263 mComplete = false;
264
265 if (!gssLibrary && NS_FAILED(gssInit())((bool)(__builtin_expect(!!(NS_FAILED_impl(gssInit())), 0)))) return;
266
267 mCtx = GSS_C_NO_CONTEXT((gss_ctx_id_t)0);
268 mMechOID = &gss_krb5_mech_oid_desc;
269
270 // if the type is kerberos we accept it as default
271 // and exit
272
273 if (package == PACKAGE_TYPE_KERBEROS) return;
274
275 // Now, look at the list of supported mechanisms,
276 // if SPNEGO is found, then use it.
277 // Otherwise, set the desired mechanism to
278 // GSS_C_NO_OID and let the system try to use
279 // the default mechanism.
280 //
281 // Using Kerberos directly (instead of negotiating
282 // with SPNEGO) may work in some cases depending
283 // on how smart the server side is.
284
285 majstat = gss_indicate_mechs_ptr((gss_indicate_mechs_type) * gssFuncs[2].func)(&minstat, &mech_set);
286 if (GSS_ERROR(majstat)(majstat & ((0377ul << 24) | (0377ul << 16)))) return;
287
288 if (mech_set) {
289 for (i = 0; i < mech_set->count; i++) {
290 item = &mech_set->elements[i];
291 if (item->length == gss_spnego_mech_oid_desc.length &&
292 !memcmp(item->elements, gss_spnego_mech_oid_desc.elements,
293 item->length)) {
294 // ok, we found it
295 mMechOID = &gss_spnego_mech_oid_desc;
296 break;
297 }
298 }
299 gss_release_oid_set_ptr((gss_release_oid_set_type) * gssFuncs[3].func)(&minstat, &mech_set);
300 }
301}
302
303void nsAuthGSSAPI::Reset() {
304 if (gssLibrary && mCtx != GSS_C_NO_CONTEXT((gss_ctx_id_t)0)) {
305 OM_uint32 minor_status;
306 gss_delete_sec_context_ptr((gss_delete_sec_context_type) * gssFuncs[4].func)(&minor_status, &mCtx, GSS_C_NO_BUFFER((gss_buffer_t)0));
307 }
308 mCtx = GSS_C_NO_CONTEXT((gss_ctx_id_t)0);
309 mComplete = false;
310}
311
312/* static */
313void nsAuthGSSAPI::Shutdown() {
314 if (gssLibrary) {
315 PR_UnloadLibrary(gssLibrary);
316 gssLibrary = nullptr;
317 }
318}
319
320/* Limitations apply to this class's thread safety. See the header file */
321NS_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" ")", "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 321
); __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" ")", "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsAuthGSSAPI\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 321); __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" ")", "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 321
); __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" ")", "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 321); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsAuthGSSAPI\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 321); __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", "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 321); 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; }
322
323NS_IMETHODIMPnsresult
324nsAuthGSSAPI::Init(const nsACString& serviceName, uint32_t serviceFlags,
325 const nsAString& domain, const nsAString& username,
326 const nsAString& password) {
327 // we don't expect to be passed any user credentials
328 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()"
, "./../../../extensions/auth/nsAuthGSSAPI.cpp", 329); MOZ_PretendNoReturn
(); } } while (0)
329 "unexpected credentials")do { if (!(domain.IsEmpty() && username.IsEmpty() &&
password.IsEmpty())) { NS_DebugBreak(NS_DEBUG_ASSERTION, "unexpected credentials"
, "domain.IsEmpty() && username.IsEmpty() && password.IsEmpty()"
, "./../../../extensions/auth/nsAuthGSSAPI.cpp", 329); MOZ_PretendNoReturn
(); } } while (0)
;
330
331 // it's critial that the caller supply a service name to be used
332 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, "./../../../extensions/auth/nsAuthGSSAPI.cpp"
, 332); return NS_ERROR_INVALID_ARG; } } while (false)
;
333
334 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)
;
335
336 if (!gssLibrary) return NS_ERROR_NOT_INITIALIZED;
337
338 mServiceName = serviceName;
339 mServiceFlags = serviceFlags;
340
341 // Init runs on background threads, so several auths may reach this
342 // concurrently.
343 static mozilla::Atomic<bool> sTelemetrySent{false};
344 if (sTelemetrySent.compareExchange(false, true)) {
345 mozilla::glean::security::ntlm_module_used.AccumulateSingleSample(
346 serviceFlags & nsIAuthModule::REQ_PROXY_AUTH
347 ? NTLM_MODULE_KERBEROS_PROXY
348 : NTLM_MODULE_KERBEROS_DIRECT);
349 }
350
351 return NS_OK;
352}
353
354NS_IMETHODIMPnsresult
355nsAuthGSSAPI::InitAsync(const nsACString& aServiceName, uint32_t aServiceFlags,
356 const nsAString& aDomain, const nsAString& aUsername,
357 const nsAString& aPassword,
358 nsIAuthModuleInitCallback* aCallback) {
359 return NS_ERROR_NOT_IMPLEMENTED;
360}
361
362NS_IMETHODIMPnsresult
363nsAuthGSSAPI::GetNextToken(const void* inToken, uint32_t inTokenLen,
364 void** outToken, uint32_t* outTokenLen) {
365 OM_uint32 major_status, minor_status;
366 OM_uint32 req_flags = 0;
367 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER{0, nullptr};
368 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr};
369 gss_buffer_t in_token_ptr = GSS_C_NO_BUFFER((gss_buffer_t)0);
370 gss_name_t server;
371 nsAutoCString userbuf;
372 nsresult rv;
373
374 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)
;
375
376 if (!gssLibrary) return NS_ERROR_NOT_INITIALIZED;
377
378 // If they've called us again after we're complete, reset to start afresh.
379 if (mComplete) Reset();
380
381 if (mServiceFlags & REQ_DELEGATE) req_flags |= GSS_C_DELEG_FLAG1;
382
383 if (mServiceFlags & REQ_MUTUAL_AUTH) req_flags |= GSS_C_MUTUAL_FLAG2;
384
385 input_token.value = (void*)mServiceName.get();
386 input_token.length = mServiceName.Length() + 1;
387
388#if defined(HAVE_RES_NINIT1)
389 res_ninit__res_ninit(&_res(*__res_state()));
390#endif
391 major_status = gss_import_name_ptr((gss_import_name_type) * gssFuncs[5].func)(&minor_status, &input_token,
392 &gss_c_nt_hostbased_service, &server);
393 input_token.value = nullptr;
394 input_token.length = 0;
395 if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16
)))
) {
396 LogGssError(major_status, minor_status, "gss_import_name() failed");
397 return NS_ERROR_FAILURE;
398 }
399
400 if (inToken) {
401 input_token.length = inTokenLen;
402 input_token.value = (void*)inToken;
403 in_token_ptr = &input_token;
404 } else if (mCtx != GSS_C_NO_CONTEXT((gss_ctx_id_t)0)) {
405 // If there is no input token, then we are starting a new
406 // authentication sequence. If we have already initialized our
407 // security context, then we're in trouble because it means that the
408 // first sequence failed. We need to bail or else we might end up in
409 // an infinite loop.
410 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)
;
411 return NS_ERROR_UNEXPECTED;
412 }
413
414#if defined(XP_MACOSX)
415 // Suppress Kerberos prompts to get credentials. See bug 240643.
416 // We can only use Mac OS X specific kerb functions if we are using
417 // the native lib
418 KLBoolean found;
419 bool doingMailTask = mServiceName.Find("imap@") ||
420 mServiceName.Find("pop@") ||
421 mServiceName.Find("smtp@") || mServiceName.Find("ldap@");
422
423 if (!doingMailTask &&
424 (KLCacheHasValidTicketsPtr &&
425 (KLCacheHasValidTickets_ptr(nullptr, kerberosVersion_V5, &found, nullptr,
426 nullptr) != klNoErr ||
427 !found))) {
428 major_status = GSS_S_FAILURE(13ul << 16);
429 minor_status = 0;
430 } else
431#endif /* XP_MACOSX */
432 major_status = gss_init_sec_context_ptr((gss_init_sec_context_type) * gssFuncs[1].func)(
433 &minor_status, GSS_C_NO_CREDENTIAL((gss_cred_id_t)0), &mCtx, server, mMechOID, req_flags,
434 GSS_C_INDEFINITE0xfffffffful, GSS_C_NO_CHANNEL_BINDINGS((gss_channel_bindings_t)0), in_token_ptr, nullptr,
435 &output_token, nullptr, nullptr);
436
437 if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16
)))
) {
438 LogGssError(major_status, minor_status, "gss_init_sec_context() failed");
439 Reset();
440 rv = NS_ERROR_FAILURE;
441 goto end;
442 }
443 if (major_status == GSS_S_COMPLETE0) {
444 // Mark ourselves as being complete, so that if we're called again
445 // we know to start afresh.
446 mComplete = true;
447 } else if (major_status == GSS_S_CONTINUE_NEEDED(1ul << (0 + 0))) {
448 //
449 // The important thing is that we do NOT reset the
450 // context here because it will be needed on the
451 // next call.
452 //
453 }
454
455 *outTokenLen = output_token.length;
456 if (output_token.length != 0) {
457 *outToken = moz_xmemdup(output_token.value, output_token.length);
458 } else {
459 *outToken = nullptr;
460 }
461
462 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token);
463
464 if (major_status == GSS_S_COMPLETE0) {
465 rv = NS_SUCCESS_AUTH_FINISHED;
466 } else {
467 rv = NS_OK;
468 }
469
470end:
471 gss_release_name_ptr((gss_release_name_type) * gssFuncs[7].func)(&minor_status, &server);
472
473 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)
474 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)
;
475 return rv;
476}
477
478NS_IMETHODIMPnsresult
479nsAuthGSSAPI::Unwrap(const void* inToken, uint32_t inTokenLen, void** outToken,
480 uint32_t* outTokenLen) {
481 OM_uint32 major_status, minor_status;
482
483 gss_buffer_desc input_token;
484 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr};
485
486 input_token.value = (void*)inToken;
487 input_token.length = inTokenLen;
488
489 major_status = gss_unwrap_ptr((gss_unwrap_type) * gssFuncs[9].func)(&minor_status, mCtx, &input_token,
490 &output_token, nullptr, nullptr);
491 if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16
)))
) {
492 LogGssError(major_status, minor_status, "gss_unwrap() failed");
493 Reset();
494 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token);
495 return NS_ERROR_FAILURE;
496 }
497
498 *outTokenLen = output_token.length;
499
500 if (output_token.length) {
501 *outToken = moz_xmemdup(output_token.value, output_token.length);
502 } else {
503 *outToken = nullptr;
504 }
505
506 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token);
507
508 return NS_OK;
509}
510
511NS_IMETHODIMPnsresult
512nsAuthGSSAPI::Wrap(const void* inToken, uint32_t inTokenLen, bool confidential,
513 void** outToken, uint32_t* outTokenLen) {
514 OM_uint32 major_status, minor_status;
515
516 gss_buffer_desc input_token;
517 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER{0, nullptr};
518
519 input_token.value = (void*)inToken;
520 input_token.length = inTokenLen;
521
522 major_status =
523 gss_wrap_ptr((gss_wrap_type) * gssFuncs[8].func)(&minor_status, mCtx, confidential, GSS_C_QOP_DEFAULT0,
524 &input_token, nullptr, &output_token);
525
526 if (GSS_ERROR(major_status)(major_status & ((0377ul << 24) | (0377ul << 16
)))
) {
527 LogGssError(major_status, minor_status, "gss_wrap() failed");
528 Reset();
529 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token);
530 return NS_ERROR_FAILURE;
531 }
532
533 *outTokenLen = output_token.length;
534
535 /* it is not possible for output_token.length to be zero */
536 *outToken = moz_xmemdup(output_token.value, output_token.length);
537 gss_release_buffer_ptr((gss_release_buffer_type) * gssFuncs[6].func)(&minor_status, &output_token);
538
539 return NS_OK;
540}