Fix parseCertificateInfo possibly in dead loop
This commit is contained in:
		
							parent
							
								
									c92153c97e
								
							
						
					
					
						commit
						41a6d1b701
					
				
					 3 changed files with 139 additions and 2 deletions
				
			
		|  | @ -367,7 +367,7 @@ class Monitor extends BeanModel { | ||||||
|                 await Monitor.sendNotification(isFirstBeat, this, bean); |                 await Monitor.sendNotification(isFirstBeat, this, bean); | ||||||
| 
 | 
 | ||||||
|                 // Clear Status Page Cache
 |                 // Clear Status Page Cache
 | ||||||
|                 debug(`[${this.name}] Check isImportant`); |                 debug(`[${this.name}] apicache clear`); | ||||||
|                 apicache.clear(); |                 apicache.clear(); | ||||||
| 
 | 
 | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  | @ -201,8 +201,13 @@ const getDaysRemaining = (validFrom, validTo) => { | ||||||
| // param: info -  the chain obtained from getPeerCertificate()
 | // param: info -  the chain obtained from getPeerCertificate()
 | ||||||
| const parseCertificateInfo = function (info) { | const parseCertificateInfo = function (info) { | ||||||
|     let link = info; |     let link = info; | ||||||
|  |     let i = 0; | ||||||
|  | 
 | ||||||
|  |     const existingList = {}; | ||||||
| 
 | 
 | ||||||
|     while (link) { |     while (link) { | ||||||
|  |         debug(`[${i}] ${link.fingerprint}`); | ||||||
|  | 
 | ||||||
|         if (!link.valid_from || !link.valid_to) { |         if (!link.valid_from || !link.valid_to) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  | @ -210,15 +215,24 @@ const parseCertificateInfo = function (info) { | ||||||
|         link.validFor = link.subjectaltname?.replace(/DNS:|IP Address:/g, "").split(", "); |         link.validFor = link.subjectaltname?.replace(/DNS:|IP Address:/g, "").split(", "); | ||||||
|         link.daysRemaining = getDaysRemaining(new Date(), link.validTo); |         link.daysRemaining = getDaysRemaining(new Date(), link.validTo); | ||||||
| 
 | 
 | ||||||
|  |         existingList[link.fingerprint] = true; | ||||||
|  | 
 | ||||||
|         // Move up the chain until loop is encountered
 |         // Move up the chain until loop is encountered
 | ||||||
|         if (link.issuerCertificate == null) { |         if (link.issuerCertificate == null) { | ||||||
|             break; |             break; | ||||||
|         } else if (link.fingerprint == link.issuerCertificate.fingerprint) { |         } else if (link.issuerCertificate.fingerprint in existingList) { | ||||||
|  |             debug(`[Last] ${link.issuerCertificate.fingerprint}`); | ||||||
|             link.issuerCertificate = null; |             link.issuerCertificate = null; | ||||||
|             break; |             break; | ||||||
|         } else { |         } else { | ||||||
|             link = link.issuerCertificate; |             link = link.issuerCertificate; | ||||||
|         } |         } | ||||||
|  | 
 | ||||||
|  |         // Should be no use, but just in case.
 | ||||||
|  |         if (i > 500) { | ||||||
|  |             throw new Error("Dead loop occurred in parseCertificateInfo"); | ||||||
|  |         } | ||||||
|  |         i++; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return info; |     return info; | ||||||
|  | @ -228,6 +242,7 @@ exports.checkCertificate = function (res) { | ||||||
|     const info = res.request.res.socket.getPeerCertificate(true); |     const info = res.request.res.socket.getPeerCertificate(true); | ||||||
|     const valid = res.request.res.socket.authorized || false; |     const valid = res.request.res.socket.authorized || false; | ||||||
| 
 | 
 | ||||||
|  |     console.log("Parsing Certificate Info"); | ||||||
|     const parsedInfo = parseCertificateInfo(info); |     const parsedInfo = parseCertificateInfo(info); | ||||||
| 
 | 
 | ||||||
|     return { |     return { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,125 @@ | ||||||
| const { genSecret, sleep } = require("../src/util"); | const { genSecret, sleep } = require("../src/util"); | ||||||
|  | const utilServerRewire = require("../server/util-server"); | ||||||
|  | 
 | ||||||
|  | describe("Test parseCertificateInfo", () => { | ||||||
|  |     it("should handle undefined", async () => { | ||||||
|  |         const parseCertificateInfo = utilServerRewire.__get__("parseCertificateInfo"); | ||||||
|  |         const info = parseCertificateInfo(undefined); | ||||||
|  |         expect(info).toEqual(undefined); | ||||||
|  |     }, 5000); | ||||||
|  | 
 | ||||||
|  |     it("should handle normal cert chain", async () => { | ||||||
|  |         const parseCertificateInfo = utilServerRewire.__get__("parseCertificateInfo"); | ||||||
|  | 
 | ||||||
|  |         const chain1 = { | ||||||
|  |             fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain2 = { | ||||||
|  |             fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain3 = { | ||||||
|  |             fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         chain1.issuerCertificate = chain2; | ||||||
|  |         chain2.issuerCertificate = chain3; | ||||||
|  |         chain3.issuerCertificate = chain3; | ||||||
|  | 
 | ||||||
|  |         const info = parseCertificateInfo(chain1); | ||||||
|  |         expect(chain1).toEqual(info); | ||||||
|  |     }, 5000); | ||||||
|  | 
 | ||||||
|  |     it("should handle cert chain with strange circle", async () => { | ||||||
|  |         const parseCertificateInfo = utilServerRewire.__get__("parseCertificateInfo"); | ||||||
|  | 
 | ||||||
|  |         const chain1 = { | ||||||
|  |             fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain2 = { | ||||||
|  |             fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain3 = { | ||||||
|  |             fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain4 = { | ||||||
|  |             fingerprint: "haha", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         chain1.issuerCertificate = chain2; | ||||||
|  |         chain2.issuerCertificate = chain3; | ||||||
|  |         chain3.issuerCertificate = chain4; | ||||||
|  |         chain4.issuerCertificate = chain2; | ||||||
|  | 
 | ||||||
|  |         const info = parseCertificateInfo(chain1); | ||||||
|  |         expect(chain1).toEqual(info); | ||||||
|  |     }, 5000); | ||||||
|  | 
 | ||||||
|  |     it("should handle cert chain with last undefined (should be happen in real, but just in case)", async () => { | ||||||
|  |         const parseCertificateInfo = utilServerRewire.__get__("parseCertificateInfo"); | ||||||
|  | 
 | ||||||
|  |         const chain1 = { | ||||||
|  |             fingerprint: "CF:2C:F3:6A:FE:6B:10:EC:44:77:C8:95:BB:96:2E:06:1F:0E:15:DA", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain2 = { | ||||||
|  |             fingerprint: "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain3 = { | ||||||
|  |             fingerprint: "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         const chain4 = { | ||||||
|  |             fingerprint: "haha", | ||||||
|  |             valid_from: "Oct 22 12:00:00 2013 GMT", | ||||||
|  |             valid_to: "Oct 22 12:00:00 2028 GMT", | ||||||
|  |             subjectaltname: "DNS:www.example.org, DNS:example.com, DNS:example.edu, DNS:example.net, DNS:example.org, DNS:www.example.com, DNS:www.example.edu, DNS:www.example.net", | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         chain1.issuerCertificate = chain2; | ||||||
|  |         chain2.issuerCertificate = chain3; | ||||||
|  |         chain3.issuerCertificate = chain4; | ||||||
|  |         chain4.issuerCertificate = undefined; | ||||||
|  | 
 | ||||||
|  |         const info = parseCertificateInfo(chain1); | ||||||
|  |         expect(chain1).toEqual(info); | ||||||
|  |     }, 5000); | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| describe("Test genSecret", () => { | describe("Test genSecret", () => { | ||||||
| 
 | 
 | ||||||
|  | @ -42,3 +163,4 @@ describe("Test reset-password", () => { | ||||||
|         await require("../extra/reset-password").main(); |         await require("../extra/reset-password").main(); | ||||||
|     }, 120000); |     }, 120000); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue