@@ -9,44 +9,46 @@ class SSHServer {
99 {
1010 hostKeys : [ require ( 'fs' ) . readFileSync ( config . getSSHConfig ( ) . hostKey . privateKeyPath ) ] ,
1111 authMethods : [ 'publickey' , 'password' ] ,
12- debug : ( msg ) => {
13- console . debug ( 'SSH Debug: ' , msg ) ;
14- } ,
12+ // debug: (msg) => {
13+ // console.debug('[ SSH Debug] ', msg);
14+ // },
1515 } ,
1616 this . handleClient . bind ( this ) ,
1717 ) ;
1818 }
1919
2020 async handleClient ( client ) {
21- console . log ( 'Client connected' , client ) ;
21+ console . log ( '[SSH] Client connected' , client ) ;
2222 client . on ( 'authentication' , async ( ctx ) => {
23- console . log ( `Authentication attempt: ${ ctx . method } ` ) ;
23+ console . log ( `[SSH] Authentication attempt: ${ ctx . method } ` ) ;
2424
2525 if ( ctx . method === 'publickey' ) {
2626 try {
27- console . log ( `CTX KEY: ${ JSON . stringify ( ctx . key ) } ` ) ;
27+ console . log ( `[SSH] CTX KEY: ${ JSON . stringify ( ctx . key ) } ` ) ;
2828 // Get the key type and key data
2929 const keyType = ctx . key . algo ;
3030 const keyData = ctx . key . data ;
3131
3232 // Format the key in the same way as stored in user's publicKeys (without comment)
3333 const keyString = `${ keyType } ${ keyData . toString ( 'base64' ) } ` ;
3434
35- console . log ( `Attempting public key authentication with key: ${ keyString } ` ) ;
35+ console . log ( `[SSH] Attempting public key authentication with key: ${ keyString } ` ) ;
3636
3737 // Find user by SSH key
3838 const user = await db . findUserBySSHKey ( keyString ) ;
3939 if ( ! user ) {
40- console . log ( 'No user found with this SSH key' ) ;
40+ console . log ( '[SSH] No user found with this SSH key' ) ;
4141 ctx . reject ( ) ;
4242 return ;
4343 }
4444
45- console . log ( `Public key authentication successful for user ${ user . username } ` ) ;
45+ console . log ( `[SSH] Public key authentication successful for user ${ user . username } ` ) ;
4646 client . username = user . username ;
47+ // Store the user's private key for later use with GitHub
48+ client . userPrivateKey = ctx . key ;
4749 ctx . accept ( ) ;
4850 } catch ( error ) {
49- console . error ( 'Error during public key authentication:' , error ) ;
51+ console . error ( '[SSH] Error during public key authentication:' , error ) ;
5052 // Let the client try the next key
5153 ctx . reject ( ) ;
5254 }
@@ -59,22 +61,22 @@ class SSHServer {
5961 const bcrypt = require ( 'bcryptjs' ) ;
6062 const isValid = await bcrypt . compare ( ctx . password , user . password ) ;
6163 if ( isValid ) {
62- console . log ( `Password authentication successful for user ${ ctx . username } ` ) ;
64+ console . log ( `[SSH] Password authentication successful for user ${ ctx . username } ` ) ;
6365 ctx . accept ( ) ;
6466 } else {
65- console . log ( `Password authentication failed for user ${ ctx . username } ` ) ;
67+ console . log ( `[SSH] Password authentication failed for user ${ ctx . username } ` ) ;
6668 ctx . reject ( ) ;
6769 }
6870 } else {
69- console . log ( `User ${ ctx . username } not found or no password set` ) ;
71+ console . log ( `[SSH] User ${ ctx . username } not found or no password set` ) ;
7072 ctx . reject ( ) ;
7173 }
7274 } catch ( error ) {
73- console . error ( 'Error during password authentication:' , error ) ;
75+ console . error ( '[SSH] Error during password authentication:' , error ) ;
7476 ctx . reject ( ) ;
7577 }
7678 } else {
77- console . log ( 'Password authentication attempted but public key was provided' ) ;
79+ console . log ( '[SSH] Password authentication attempted but public key was provided' ) ;
7880 ctx . reject ( ) ;
7981 }
8082 } else {
@@ -84,12 +86,12 @@ class SSHServer {
8486 } ) ;
8587
8688 client . on ( 'ready' , ( ) => {
87- console . log ( `Client ready: ${ client . username } ` ) ;
89+ console . log ( `[SSH] Client ready: ${ client . username } ` ) ;
8890 client . on ( 'session' , this . handleSession . bind ( this ) ) ;
8991 } ) ;
9092
9193 client . on ( 'error' , ( err ) => {
92- console . error ( 'Client error:' , err ) ;
94+ console . error ( '[SSH] Client error:' , err ) ;
9395 } ) ;
9496 }
9597
@@ -100,7 +102,7 @@ class SSHServer {
100102 const command = info . command ;
101103
102104 // Parse Git command
103- console . log ( 'Command' , command ) ;
105+ console . log ( '[SSH] Command' , command ) ;
104106 if ( command . startsWith ( 'git-' ) ) {
105107 // Extract the repository path from the command
106108 // Remove quotes and 'git-' prefix, then trim any leading/trailing slashes
@@ -113,6 +115,7 @@ class SSHServer {
113115 const req = {
114116 method : command === 'git-upload-pack' ? 'GET' : 'POST' ,
115117 originalUrl : repoPath ,
118+ isSSH : true ,
116119 headers : {
117120 'user-agent' : 'git/2.0.0' ,
118121 'content-type' :
@@ -121,15 +124,85 @@ class SSHServer {
121124 } ;
122125
123126 try {
124- console . log ( 'Executing chain' , req ) ;
127+ console . log ( '[SSH] Executing chain' , req ) ;
125128 const action = await chain . executeChain ( req ) ;
126- stream . write ( action . getContent ( ) ) ;
127- stream . end ( ) ;
129+
130+ console . log ( '[SSH] Action' , action ) ;
131+
132+ if ( action . error || action . blocked ) {
133+ // If there's an error or the action is blocked, send the error message
134+ console . log (
135+ '[SSH] Action error or blocked' ,
136+ action . errorMessage || action . blockedMessage ,
137+ ) ;
138+ stream . write ( action . errorMessage || action . blockedMessage ) ;
139+ stream . end ( ) ;
140+ return ;
141+ }
142+
143+ // Create SSH connection to GitHub
144+ const githubSsh = new ssh2 . Client ( ) ;
145+
146+ console . log ( '[SSH] Creating SSH connection to GitHub' ) ;
147+ githubSsh . on ( 'ready' , ( ) => {
148+ console . log ( '[SSH] Connected to GitHub' ) ;
149+
150+ // Execute the Git command on GitHub
151+ githubSsh . exec ( command , { env : { GIT_PROTOCOL : 'version=2' } } , ( err , githubStream ) => {
152+ if ( err ) {
153+ console . error ( '[SSH] Failed to execute command on GitHub:' , err ) ;
154+ stream . write ( err . toString ( ) ) ;
155+ stream . end ( ) ;
156+ return ;
157+ }
158+
159+ // Pipe data between client and GitHub
160+ stream . pipe ( githubStream ) . pipe ( stream ) ;
161+
162+ githubStream . on ( 'exit' , ( code ) => {
163+ console . log ( `[SSH] GitHub command exited with code ${ code } ` ) ;
164+ githubSsh . end ( ) ;
165+ } ) ;
166+ } ) ;
167+ } ) ;
168+
169+ githubSsh . on ( 'error' , ( err ) => {
170+ console . error ( '[SSH] GitHub SSH error:' , err ) ;
171+ stream . write ( err . toString ( ) ) ;
172+ stream . end ( ) ;
173+ } ) ;
174+
175+ // Get the client's SSH key that was used for authentication
176+ // console.log('[SSH] Session:', session);
177+ const clientKey = session . _channel . _client . userPrivateKey ;
178+ console . log ( '[SSH] Client key:' , clientKey ? 'Available' : 'Not available' ) ;
179+
180+ if ( clientKey ) {
181+ console . log ( '[SSH] Using client key to connect to GitHub' ) ;
182+ // Use the client's private key to connect to GitHub
183+ githubSsh . connect ( {
184+ host : 'github.com' ,
185+ port : 22 ,
186+ username : 'git' ,
187+ privateKey : clientKey ,
188+ } ) ;
189+ } else {
190+ console . log ( '[SSH] No client key available, using proxy key' ) ;
191+ // Fallback to proxy's SSH key if no client key is available
192+ githubSsh . connect ( {
193+ host : 'github.com' ,
194+ port : 22 ,
195+ username : 'git' ,
196+ privateKey : require ( 'fs' ) . readFileSync ( config . getSSHConfig ( ) . hostKey . privateKeyPath ) ,
197+ } ) ;
198+ }
128199 } catch ( error ) {
200+ console . error ( '[SSH] Error during SSH connection:' , error ) ;
129201 stream . write ( error . toString ( ) ) ;
130202 stream . end ( ) ;
131203 }
132204 } else {
205+ console . log ( '[SSH] Unsupported command' , command ) ;
133206 stream . write ( 'Unsupported command' ) ;
134207 stream . end ( ) ;
135208 }
@@ -139,7 +212,7 @@ class SSHServer {
139212 start ( ) {
140213 const port = config . getSSHConfig ( ) . port ;
141214 this . server . listen ( port , '0.0.0.0' , ( ) => {
142- console . log ( `SSH server listening on port ${ port } ` ) ;
215+ console . log ( `[ SSH] Server listening on port ${ port } ` ) ;
143216 } ) ;
144217 }
145218}
0 commit comments