tenseleyflow/gitswitch / 1049f51

Browse files

fix: improve SSH connection test for git hosting services

- Use git@github.com instead of github.com for SSH tests
- Use ssh -T (no TTY) since git hosts don't allow shell commands
- Check for success messages in output instead of exit code
(GitHub returns exit 1 even on successful auth)
- Downgrade SSH test failures to debug level since they're optional
Authored by espadonne
SHA
1049f51f230b0ae54a8e7948ec4d9919de1b0742
Parents
3559e36
Tree
ffc25c0

2 changed files

StatusFile+-
M src/accounts.c 2 2
M src/ssh_manager.c 23 18
src/accounts.cmodified
@@ -118,8 +118,8 @@ int accounts_switch(gitswitch_ctx_t *ctx, const char *identifier) {
118
                             log_warning("SSH connection test failed for %s", account->ssh_host_alias);
118
                             log_warning("SSH connection test failed for %s", account->ssh_host_alias);
119
                         }
119
                         }
120
                     } else {
120
                     } else {
121
-                        /* Test with default GitHub host */
121
+                        /* Test with default GitHub host (git@ is required for GitHub SSH) */
122
-                        if (ssh_test_connection(account, "github.com") == 0) {
122
+                        if (ssh_test_connection(account, "git@github.com") == 0) {
123
                             log_info("SSH connection test passed for github.com");
123
                             log_info("SSH connection test passed for github.com");
124
                         } else {
124
                         } else {
125
                             log_debug("SSH connection test failed for github.com (this may be normal)");
125
                             log_debug("SSH connection test failed for github.com (this may be normal)");
src/ssh_manager.cmodified
@@ -561,11 +561,13 @@ int ssh_test_connection(const account_t *account, const char *host) {
561
     
561
     
562
     log_debug("Testing SSH connection to: %s", host);
562
     log_debug("Testing SSH connection to: %s", host);
563
     
563
     
564
-    /* Build SSH test command */
564
+    /* Build SSH test command using -T (no TTY) for git hosting services
565
+     * GitHub/GitLab/Bitbucket don't allow shell commands, they return a
566
+     * greeting message on successful auth (exit code 1 but with success message) */
565
     if (strlen(account->ssh_host_alias) > 0) {
567
     if (strlen(account->ssh_host_alias) > 0) {
566
         /* Use host alias */
568
         /* Use host alias */
567
-        if ((size_t)snprintf(command, sizeof(command), 
569
+        if ((size_t)snprintf(command, sizeof(command),
568
-                            "ssh -o ConnectTimeout=5 -o BatchMode=yes %s echo 'SSH connection test successful'",
570
+                            "ssh -T -o ConnectTimeout=5 -o BatchMode=yes %s 2>&1",
569
                             account->ssh_host_alias) >= sizeof(command)) {
571
                             account->ssh_host_alias) >= sizeof(command)) {
570
             set_error(ERR_INVALID_ARGS, "SSH test command too long");
572
             set_error(ERR_INVALID_ARGS, "SSH test command too long");
571
             return -1;
573
             return -1;
@@ -576,28 +578,31 @@ int ssh_test_connection(const account_t *account, const char *host) {
576
         if (expand_path(account->ssh_key_path, expanded_key_path, sizeof(expanded_key_path)) != 0) {
578
         if (expand_path(account->ssh_key_path, expanded_key_path, sizeof(expanded_key_path)) != 0) {
577
             return -1;
579
             return -1;
578
         }
580
         }
579
-        
581
+
580
         if ((size_t)snprintf(command, sizeof(command),
582
         if ((size_t)snprintf(command, sizeof(command),
581
-                            "ssh -o ConnectTimeout=5 -o BatchMode=yes -i '%s' %s echo 'SSH connection test successful'",
583
+                            "ssh -T -o ConnectTimeout=5 -o BatchMode=yes -i '%s' %s 2>&1",
582
                             expanded_key_path, host) >= sizeof(command)) {
584
                             expanded_key_path, host) >= sizeof(command)) {
583
             set_error(ERR_INVALID_ARGS, "SSH test command too long");
585
             set_error(ERR_INVALID_ARGS, "SSH test command too long");
584
             return -1;
586
             return -1;
585
         }
587
         }
586
     }
588
     }
587
-    
589
+
588
-    /* Execute SSH test */
590
+    /* Execute SSH test - for git hosts, check output for success indicators
589
-    if (execute_ssh_command(command, output, sizeof(output)) != 0) {
591
+     * Note: GitHub returns exit code 1 even on success (no shell access) */
590
-        set_error(ERR_SSH_CONNECTION_FAILED, "SSH connection test failed to %s: %s", host, output);
592
+    (void)execute_ssh_command(command, output, sizeof(output));
591
-        return -1;
593
+
592
-    }
594
+    /* Check for authentication success messages from common git hosting services */
593
-    
595
+    if (strstr(output, "successfully authenticated") ||  /* GitHub */
594
-    if (!strstr(output, "SSH connection test successful")) {
596
+        strstr(output, "Welcome to GitLab") ||           /* GitLab */
595
-        set_error(ERR_SSH_CONNECTION_FAILED, "SSH connection test did not return expected output");
597
+        strstr(output, "logged in as") ||                /* Bitbucket */
596
-        return -1;
598
+        strstr(output, "Hi ") ||                         /* GitHub greeting */
599
+        strstr(output, "authentication successful")) {   /* Generic */
600
+        log_debug("SSH authentication successful to %s", host);
601
+        return 0;
597
     }
602
     }
598
-    
603
+
599
-    log_info("SSH connection test successful to: %s", host);
604
+    log_debug("SSH connection test failed to %s: %s", host, output);
600
-    return 0;
605
+    return -1;
601
 }
606
 }
602
 
607
 
603
 /* Internal helper functions */
608
 /* Internal helper functions */