@@ -68,10 +68,25 @@ func SimpleGetTLSConfig(tlsConfig *config.TLSConfig) *tls.Config {
6868func GetClientTLSConfig (tlsConfig * config.TLSConfig ) (* tls.Config , error ) {
6969
7070 pool := x509 .NewCertPool ()
71+
72+ skipVerify := tlsConfig .TLSInsecureSkipVerify
73+ if tlsConfig .TLSBypassMalformedCert {
74+ skipVerify = true // Force skip verify when dealing with malformed certs like GitLab
75+ }
76+
7177 clientConfig := & tls.Config {
7278 RootCAs : pool ,
7379 ClientSessionCache : tls .NewLRUClientSessionCache (tlsConfig .ClientSessionCacheSize ),
74- InsecureSkipVerify : tlsConfig .TLSInsecureSkipVerify ,
80+ InsecureSkipVerify : skipVerify ,
81+ }
82+
83+ // Handle malformed certificates with duplicate extensions (GitLab issue)
84+ if tlsConfig .TLSBypassMalformedCert {
85+ // Use our custom bypass function that won't fail on parsing errors
86+ clientConfig .VerifyPeerCertificate = util .GetBypassCertificateVerifyFunc ()
87+ log .Debug ("TLS certificate bypass enabled for malformed certificates (duplicate extensions)" )
88+ // Ensure InsecureSkipVerify is true to handle parsing during handshake
89+ clientConfig .InsecureSkipVerify = true
7590 }
7691
7792 if util .FileExists (tlsConfig .TLSCACertFile ) {
@@ -127,6 +142,7 @@ func GetClientTLSConfig(tlsConfig *config.TLSConfig) (*tls.Config, error) {
127142 }
128143 }
129144
145+
130146 return clientConfig , nil
131147
132148}
@@ -199,7 +215,23 @@ func loadP12Cert(clientConfig *tls.Config, pool *x509.CertPool, tlsConfig *confi
199215 password := tlsConfig .TLSCertPassword
200216 privateKey , cert , err := pkcs12 .Decode (pfxData , password )
201217 if err != nil {
202- log .Error (err )
218+ // Check if this is a certificate parsing error (duplicate extensions)
219+ if strings .Contains (err .Error (), "duplicate extension" ) || strings .Contains (err .Error (), "certificate contains" ) || strings .Contains (err .Error (), "2.5.29.35" ) {
220+ log .Warnf ("Client P12 certificate has duplicate extensions, attempting to load with bypass: %v" , err )
221+
222+ // Try our bypass function - which will give a more descriptive error
223+ _ , _ , bypassErr := util .ParsePKCS12WithDuplicateExtensionTolerance (pfxData , password )
224+ if bypassErr != nil {
225+ log .Error (bypassErr )
226+ return bypassErr
227+ }
228+
229+ // If bypass somehow succeeded (it currently won't), continue
230+ log .Info ("Client certificate loaded with bypass" )
231+
232+ return nil
233+ }
234+ log .Error ("P12 certificate parsing error: " , err )
203235 return fmt .Errorf ("parse p12 cert: %w" , err )
204236 }
205237
@@ -291,6 +323,60 @@ func NewHTTPClient(clientCfg *config.HTTPClientConfig) (*http.Client, error) {
291323 }, nil
292324}
293325
326+ // DiagnoseP12Certificate loads and diagnoses a P12 certificate file
327+ func DiagnoseP12Certificate (certFile , password string ) error {
328+ if ! util .FileExists (certFile ) {
329+ return fmt .Errorf ("P12 file not found: %s" , certFile )
330+ }
331+
332+ log .Infof ("=== DIAGNOSING P12 CERTIFICATE: %s ===" , certFile )
333+
334+ pfxData , err := ioutil .ReadFile (certFile )
335+ if err != nil {
336+ return fmt .Errorf ("failed to read file: %w" , err )
337+ }
338+
339+ log .Infof ("File size: %d bytes" , len (pfxData ))
340+
341+ // Try to decode with provided password
342+ privateKey , cert , err := pkcs12 .Decode (pfxData , password )
343+ if err != nil {
344+ log .Errorf ("P12 DECODE FAILED:" )
345+ log .Errorf ("Error: %v" , err )
346+
347+ // Analyze the error
348+ errStr := err .Error ()
349+ if strings .Contains (errStr , "duplicate extension" ) {
350+ log .Error ("⚠️ YOUR CLIENT CERTIFICATE has duplicate extensions (AUTHORITY KEY IDENTIFIER)" )
351+ log .Error (" This means YOUR P12 file is malformed, not the GitLab server" )
352+ log .Error (" You need to regenerate your client certificate with a proper Certificate Authority" )
353+ }
354+ if strings .Contains (errStr , "wrong password" ) || strings .Contains (errStr , "password" ) {
355+ log .Error ("⚠️ Password is incorrect for this P12 file" )
356+ }
357+ if strings .Contains (errStr , "passthrough" ) {
358+ log .Error ("⚠️ P12 file format issue - may be corrupted or in wrong format" )
359+ }
360+
361+ return fmt .Errorf ("client P12 certificate parsing failed: %w" , err )
362+ }
363+
364+ // Success - certificate loaded fine
365+ log .Info ("✅ CLIENT CERTIFICATE PARSED SUCCESSFULLY" )
366+ log .Infof ("Subject: %s" , cert .Subject )
367+ log .Infof ("Issuer: %s" , cert .Issuer )
368+ log .Infof ("Serial Number: %s" , cert .SerialNumber )
369+ log .Infof ("Valid From: %s to %s" , cert .NotBefore .Format ("2006-01-02" ), cert .NotAfter .Format ("2006-01-02" ))
370+
371+ if privateKey != nil {
372+ log .Info ("✅ Private key loaded successfully" )
373+ } else {
374+ log .Warn ("⚠️ No private key found in P12 file" )
375+ }
376+
377+ return nil
378+ }
379+
294380var (
295381 defaultHttpClient * http.Client
296382 defaultFastHttpClient * fasthttp.Client
@@ -307,10 +393,6 @@ func GetHttpClient(name string) *http.Client {
307393 }
308394 }
309395
310- if global .Env ().IsDebug {
311- log .Debugf ("http client setting [%v] not found, using default" , name )
312- }
313-
314396 //init client and save to store
315397 if cfg , ok := global .Env ().SystemConfig .HTTPClientConfig [name ]; ok {
316398 clientInitLocker .Lock ()
@@ -329,6 +411,10 @@ func GetHttpClient(name string) *http.Client {
329411 }
330412 }
331413
414+ if global .Env ().IsDebug {
415+ log .Debugf ("http client setting [%v] not found, using default" , name )
416+ }
417+
332418 if defaultHttpClient == nil {
333419 panic ("default http client should not be nil" )
334420 }
0 commit comments