mirror of
				https://github.com/Ylianst/MeshCentral.git
				synced 2025-03-09 15:40:18 +00:00 
			
		
		
		
	Added SSH key auth and remember to agent Win-SSH link, #3108
This commit is contained in:
		
							parent
							
								
									e25cec9c5e
								
							
						
					
					
						commit
						a928d3cada
					
				
					 3 changed files with 132 additions and 29 deletions
				
			
		
							
								
								
									
										85
									
								
								apprelays.js
									
										
									
									
									
								
							
							
						
						
									
										85
									
								
								apprelays.js
									
										
									
									
									
								
							|  | @ -290,6 +290,34 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) { | |||
|         delete obj.ws; | ||||
|     }; | ||||
| 
 | ||||
|     // Save SSH credentials into device
 | ||||
|     function saveSshCredentials() { | ||||
|         parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) { | ||||
|             if ((err != null) || (nodes == null) || (nodes.length != 1)) return; | ||||
|             const node = nodes[0]; | ||||
|             const changed = (node.ssh == null); | ||||
| 
 | ||||
|             // Check if credentials are the same
 | ||||
|             //if ((typeof node.ssh == 'object') && (node.ssh.u == obj.username) && (node.ssh.p == obj.password)) return; // TODO
 | ||||
| 
 | ||||
|             // Save the credentials
 | ||||
|             if (obj.password != null) { | ||||
|                 node.ssh = { u: obj.username, p: obj.password }; | ||||
|             } else if (obj.privateKey != null) { | ||||
|                 node.ssh = { u: obj.username, k: obj.privateKey, kp: obj.privateKeyPass }; | ||||
|             } else return; | ||||
|             parent.parent.db.Set(node); | ||||
| 
 | ||||
|             // Event node change if needed
 | ||||
|             if (changed) { | ||||
|                 // Event the node change
 | ||||
|                 var event = { etype: 'node', action: 'changenode', nodeid: obj.cookie.nodeid, domain: domain.id, userid: obj.cookie.userid, node: parent.CloneSafeNode(node), msg: "Changed SSH credentials" }; | ||||
|                 if (parent.parent.db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
 | ||||
|                 parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(node.meshid, [obj.cookie.nodeid]), obj, event); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     // Decode the authentication cookie
 | ||||
|     obj.cookie = parent.parent.decodeCookie(req.query.auth, parent.parent.loginCookieEncryptionKey); | ||||
|     if (obj.cookie == null) { obj.ws.send(JSON.stringify({ action: 'sessionerror' })); obj.close(); return; } | ||||
|  | @ -317,6 +345,9 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) { | |||
|                     const Client = require('ssh2').Client; | ||||
|                     obj.sshClient = new Client(); | ||||
|                     obj.sshClient.on('ready', function () { // Authentication was successful.
 | ||||
|                         // If requested, save the credentials
 | ||||
|                         if (obj.keep === true) saveSshCredentials(); | ||||
| 
 | ||||
|                         obj.sshClient.shell(function (err, stream) { // Start a remote shell
 | ||||
|                             if (err) { obj.close(); return; } | ||||
|                             obj.sshShell = stream; | ||||
|  | @ -327,7 +358,8 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) { | |||
|                         obj.ws.send(JSON.stringify({ action: 'connected' })); | ||||
|                     }); | ||||
|                     obj.sshClient.on('error', function (err) { | ||||
|                         if (err.level == 'client-authentication') { obj.ws.send(JSON.stringify({ action: 'autherror' })); } | ||||
|                         if (err.level == 'client-authentication') { try { obj.ws.send(JSON.stringify({ action: 'autherror' })); } catch (ex) { } } | ||||
|                         if (err.level == 'client-timeout') { try { obj.ws.send(JSON.stringify({ action: 'sessiontimeout' })); } catch (ex) { } } | ||||
|                         obj.close(); | ||||
|                     }); | ||||
| 
 | ||||
|  | @ -336,10 +368,10 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) { | |||
| 
 | ||||
|                     // Connect the SSH module to the serial tunnel
 | ||||
|                     var connectionOptions = { sock: obj.ser } | ||||
|                     if (typeof obj.username == 'string') { connectionOptions.username = obj.username; delete obj.username; } | ||||
|                     if (typeof obj.password == 'string') { connectionOptions.password = obj.password; delete obj.password; } | ||||
|                     if (typeof obj.privateKey == 'string') { connectionOptions.privateKey = obj.privateKey; delete obj.privateKey; } | ||||
|                     if (typeof obj.privateKeyPass == 'string') { connectionOptions.passphrase = obj.privateKeyPass; delete obj.privateKeyPass; } | ||||
|                     if (typeof obj.username == 'string') { connectionOptions.username = obj.username; } | ||||
|                     if (typeof obj.password == 'string') { connectionOptions.password = obj.password; } | ||||
|                     if (typeof obj.privateKey == 'string') { connectionOptions.privateKey = obj.privateKey; } | ||||
|                     if (typeof obj.privateKeyPass == 'string') { connectionOptions.passphrase = obj.privateKeyPass; } | ||||
|                     try { | ||||
|                         obj.sshClient.connect(connectionOptions); | ||||
|                     } catch (ex) { | ||||
|  | @ -376,16 +408,41 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) { | |||
|                 if (typeof msg.action != 'string') return; | ||||
|                 switch (msg.action) { | ||||
|                     case 'connect': { | ||||
|                         // Verify inputs
 | ||||
|                         if ((typeof msg.username != 'string') || (typeof msg.password != 'string')) break; | ||||
|                         if ((typeof msg.rows != 'number') || (typeof msg.cols != 'number') || (typeof msg.height != 'number') || (typeof msg.width != 'number')) break; | ||||
|                         if (msg.useexisting) { | ||||
|                             // Check if we have SSH credentials for this device
 | ||||
|                             parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) { | ||||
|                                 if ((err != null) || (nodes == null) || (nodes.length != 1)) return; | ||||
|                                 const node = nodes[0]; | ||||
|                                 if ((node.ssh == null) || (typeof node.ssh != 'object') || (typeof node.ssh.u != 'string') || ((typeof node.ssh.p != 'string') && (typeof node.ssh.k != 'string'))) { | ||||
|                                     // Send a request for SSH authentication
 | ||||
|                                     try { ws.send(JSON.stringify({ action: 'sshauth' })) } catch (ex) { } | ||||
|                                 } else { | ||||
|                                     // Use our existing credentials
 | ||||
|                                     obj.termSize = msg; | ||||
|                                     obj.keep = false; | ||||
|                                     obj.username = node.ssh.u; | ||||
|                                     if (typeof node.ssh.p == 'string') { | ||||
|                                         obj.password = node.ssh.p; | ||||
|                                     } else if (typeof node.ssh.k == 'string') { | ||||
|                                         obj.privateKey = node.ssh.k; | ||||
|                                         obj.privateKeyPass = node.ssh.kp; | ||||
|                                     } | ||||
|                                     startRelayConnection(); | ||||
|                                 } | ||||
|                             }); | ||||
|                         } else { | ||||
|                             // Verify inputs
 | ||||
|                             if ((typeof msg.username != 'string') || ((typeof msg.password != 'string') && (typeof msg.key != 'string'))) break; | ||||
|                             if ((typeof msg.rows != 'number') || (typeof msg.cols != 'number') || (typeof msg.height != 'number') || (typeof msg.width != 'number')) break; | ||||
| 
 | ||||
|                         obj.termSize = msg; | ||||
|                         obj.username = msg.username; | ||||
|                         obj.password = msg.password; | ||||
|                         obj.privateKey = msg.key; | ||||
|                         obj.privateKeyPass = msg.keypass; | ||||
|                         startRelayConnection(); | ||||
|                             obj.termSize = msg; | ||||
|                             obj.keep = msg.keep; // If true, keep store credentials on the server if the SSH tunnel connected succesfully.
 | ||||
|                             obj.username = msg.username; | ||||
|                             obj.password = msg.password; | ||||
|                             obj.privateKey = msg.key; | ||||
|                             obj.privateKeyPass = msg.keypass; | ||||
|                             startRelayConnection(); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                     case 'resize': { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue