diff -ruN openssh-3.4p1-dist/README.agent-retry-patch openssh-3.4p1/README.agent-retry-patch --- openssh-3.4p1-dist/README.agent-retry-patch Wed Dec 31 16:00:00 1969 +++ openssh-3.4p1/README.agent-retry-patch Fri Jun 28 21:18:24 2002 @@ -0,0 +1,27 @@ +Agent connection retry mechanism +2002-06-26 +Jos Backus + +This hack allows the user to specify how often ssh retries its attempt to +contact the authentication agent (ssh-agent), as well as the delay time +between each attempt. By default only one attempt is made (i.e. no retries) +without any subsequent delay. + +The client config options are: + + AuthMaxRetries + AuthRetryDelay + +Details: +- authfd.c: add sigalrm(), backoff() and modify + ssh_get_authentication_socket() and ssh_get_authentication_connection() to + accept options.auth_max_retries and options.auth_retry_delay. + Modify ssh_get_authentication_connection() to implement the backoff/retry + mechanism. +- authfd.h: fix prototypes. +- channels.c, ssh-add.c: cause no retries in call to + ssh_get_authentication_socket(). +- clientloop.c, ssh.c, ssh{1,2}connect.c: pass auth retry options to + ssh_get_authentication_socket(). +- readconf.[ch]: add support for the ``authmaxretries'' and ``authretrydelay'' + keywords. diff -ruN openssh-3.4p1-dist/authfd.c openssh-3.4p1/authfd.c --- openssh-3.4p1-dist/authfd.c Tue Jun 25 16:22:55 2002 +++ openssh-3.4p1/authfd.c Mon Jul 1 15:54:08 2002 @@ -61,13 +61,46 @@ ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \ (x == SSH2_AGENT_FAILURE)) +/* dummy signal handler */ +static void +sigalrm(int s) +{ +} + +static void +backoff(int min, int max) +{ + struct itimerval itv; + sigset_t set; + struct sigaction sa; + double delta; + + sa.sa_handler = sigalrm; + sigaction(SIGALRM, &sa, NULL); + + delta = min + (max - min) * ((double)arc4random() / UINT_MAX); + timerclear(&itv.it_interval); + itv.it_value.tv_sec = delta; + itv.it_value.tv_usec = 1000000 * (delta - itv.it_value.tv_sec); + + debug("%s: sleeping %ld.%ld seconds...", + __func__, itv.it_value.tv_sec, itv.it_value.tv_usec); + setitimer(ITIMER_REAL, &itv, (struct itimerval *)NULL); + + /* use current procmask */ + sigprocmask(0, 0, &set); + sigsuspend(&set); + debug("%s: done.", __func__); +} + /* Returns the number of the authentication fd, or -1 if there is none. */ int -ssh_get_authentication_socket(void) +ssh_get_authentication_socket(int max_retries, int retry_delay) { const char *authsocket; int sock; + int retries = 0; struct sockaddr_un sunaddr; authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); @@ -77,19 +110,32 @@ sunaddr.sun_family = AF_UNIX; strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); - sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) - return -1; - - /* close on exec */ - if (fcntl(sock, F_SETFD, 1) == -1) { - close(sock); - return -1; - } - if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) { - close(sock); - return -1; + for (;;) { + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) + return -1; + + /* close on exec */ + if (fcntl(sock, F_SETFD, 1) == -1) { + close(sock); + return -1; + } + if (connect(sock, (struct sockaddr *) & sunaddr, sizeof sunaddr) < 0) { + int err = errno; + close(sock); + if (err == ECONNREFUSED && ++retries <= max_retries) { + debug("%s: attempt %d failed; sleeping at most %d seconds.", + __func__,retries, retry_delay); + backoff(1, retry_delay); + } else { + error("ssh_get_authentication_socket: " + "maximum number of retries (%d) exceeded", max_retries); + return -1; + } + } else + break; } + return sock; } @@ -172,12 +218,12 @@ */ AuthenticationConnection * -ssh_get_authentication_connection(void) +ssh_get_authentication_connection(int max_retries, int retry_delay) { AuthenticationConnection *auth; int sock; - sock = ssh_get_authentication_socket(); + sock = ssh_get_authentication_socket(max_retries, retry_delay); /* * Fail if we couldn't obtain a connection. This happens if we diff -ruN openssh-3.4p1-dist/authfd.h openssh-3.4p1/authfd.h --- openssh-3.4p1-dist/authfd.h Thu Jun 20 17:41:52 2002 +++ openssh-3.4p1/authfd.h Wed Jun 26 10:50:14 2002 @@ -66,10 +66,10 @@ int howmany; } AuthenticationConnection; -int ssh_get_authentication_socket(void); +int ssh_get_authentication_socket(int, int); void ssh_close_authentication_socket(int); -AuthenticationConnection *ssh_get_authentication_connection(void); +AuthenticationConnection *ssh_get_authentication_connection(int, int); void ssh_close_authentication_connection(AuthenticationConnection *); int ssh_get_num_identities(AuthenticationConnection *, int); Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); diff -ruN openssh-3.4p1-dist/channels.c openssh-3.4p1/channels.c --- openssh-3.4p1-dist/channels.c Wed Jun 26 02:14:43 2002 +++ openssh-3.4p1/channels.c Wed Jun 26 10:48:47 2002 @@ -2721,7 +2721,7 @@ * Get a connection to the local authentication agent (this may again * get forwarded). */ - sock = ssh_get_authentication_socket(); + sock = ssh_get_authentication_socket(0, 0); /* * If we could not connect the agent, send an error message back to diff -ruN openssh-3.4p1-dist/clientloop.c openssh-3.4p1/clientloop.c --- openssh-3.4p1-dist/clientloop.c Tue Jun 25 16:17:37 2002 +++ openssh-3.4p1/clientloop.c Wed Jun 26 10:48:47 2002 @@ -1191,7 +1191,8 @@ error("Warning: this is probably a break in attempt by a malicious server."); return NULL; } - sock = ssh_get_authentication_socket(); + sock = ssh_get_authentication_socket(options.auth_max_retries, + options.auth_retry_delay); if (sock < 0) return NULL; c = channel_new("authentication agent connection", diff -ruN openssh-3.4p1-dist/readconf.c openssh-3.4p1/readconf.c --- openssh-3.4p1-dist/readconf.c Thu Jun 20 17:41:52 2002 +++ openssh-3.4p1/readconf.c Wed Jun 26 10:51:01 2002 @@ -114,6 +114,7 @@ oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, oClearAllForwardings, oNoHostAuthenticationForLocalhost, + oAuthMaxRetries, oAuthRetryDelay, oDeprecated } OpCodes; @@ -184,6 +185,8 @@ { "hostkeyalgorithms", oHostKeyAlgorithms }, { "bindaddress", oBindAddress }, { "smartcarddevice", oSmartcardDevice }, + { "authmaxretries", oAuthMaxRetries }, + { "authretrydelay", oAuthRetryDelay }, { "clearallforwardings", oClearAllForwardings }, { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost }, { NULL, oBadOption } @@ -674,6 +677,14 @@ filename, linenum, keyword); return 0; + case oAuthMaxRetries: + intptr = &options->auth_max_retries; + goto parse_int; + + case oAuthRetryDelay: + intptr = &options->auth_retry_delay; + goto parse_int; + default: fatal("process_config_line: Unimplemented opcode %d", opcode); } @@ -792,6 +803,8 @@ options->preferred_authentications = NULL; options->bind_address = NULL; options->smartcard_device = NULL; + options->auth_max_retries = -1; + options->auth_retry_delay = -1; options->no_host_authentication_for_localhost = - 1; } @@ -905,6 +918,10 @@ options->log_level = SYSLOG_LEVEL_INFO; if (options->clear_forwardings == 1) clear_forwardings(options); + if (options->auth_max_retries == -1) + options->auth_max_retries = 0; + if (options->auth_retry_delay == -1) + options->auth_retry_delay = 0; if (options->no_host_authentication_for_localhost == - 1) options->no_host_authentication_for_localhost = 0; /* options->proxy_command should not be set by default */ diff -ruN openssh-3.4p1-dist/readconf.h openssh-3.4p1/readconf.h --- openssh-3.4p1-dist/readconf.h Sun Jun 9 13:04:03 2002 +++ openssh-3.4p1/readconf.h Wed Jun 26 10:48:47 2002 @@ -56,6 +56,8 @@ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ int batch_mode; /* Batch mode: do not ask for passwords. */ int check_host_ip; /* Also keep track of keys for IP address */ + int auth_max_retries; /* max attempts to contact ssh-agent */ + int auth_retry_delay; /* delay between ssh-agent contact attempts */ int strict_host_key_checking; /* Strict host key checking. */ int compression; /* Compress packets in both directions. */ int compression_level; /* Compression level 1 (fast) to 9 diff -ruN openssh-3.4p1-dist/ssh-add.c openssh-3.4p1/ssh-add.c --- openssh-3.4p1-dist/ssh-add.c Thu Jun 20 17:41:52 2002 +++ openssh-3.4p1/ssh-add.c Wed Jun 26 10:48:47 2002 @@ -314,7 +314,7 @@ SSLeay_add_all_algorithms(); /* At first, get a connection to the authentication agent. */ - ac = ssh_get_authentication_connection(); + ac = ssh_get_authentication_connection(0, 0); if (ac == NULL) { fprintf(stderr, "Could not open a connection to your authentication agent.\n"); exit(2); diff -ruN openssh-3.4p1-dist/ssh.c openssh-3.4p1/ssh.c --- openssh-3.4p1-dist/ssh.c Wed Jun 12 09:11:13 2002 +++ openssh-3.4p1/ssh.c Wed Jun 26 10:48:47 2002 @@ -819,7 +819,8 @@ { if (options.forward_agent) { /* Clear agent forwarding if we don\'t have an agent. */ - int authfd = ssh_get_authentication_socket(); + int authfd = ssh_get_authentication_socket(options.auth_max_retries, + options.auth_retry_delay); if (authfd < 0) options.forward_agent = 0; else diff -ruN openssh-3.4p1-dist/sshconnect1.c openssh-3.4p1/sshconnect1.c --- openssh-3.4p1-dist/sshconnect1.c Thu Jun 6 12:57:34 2002 +++ openssh-3.4p1/sshconnect1.c Wed Jun 26 10:48:47 2002 @@ -74,7 +74,8 @@ BIGNUM *challenge; /* Get connection to the agent. */ - auth = ssh_get_authentication_connection(); + auth = ssh_get_authentication_connection(options.auth_max_retries, + options.auth_retry_delay); if (!auth) return 0; diff -ruN openssh-3.4p1-dist/sshconnect2.c openssh-3.4p1/sshconnect2.c --- openssh-3.4p1-dist/sshconnect2.c Sun Jun 23 14:23:21 2002 +++ openssh-3.4p1/sshconnect2.c Wed Jun 26 10:48:47 2002 @@ -248,7 +248,9 @@ /* setup authentication context */ memset(&authctxt, 0, sizeof(authctxt)); - authctxt.agent = ssh_get_authentication_connection(); + authctxt.agent = + ssh_get_authentication_connection(options.auth_max_retries, + options.auth_retry_delay); authctxt.server_user = server_user; authctxt.local_user = local_user; authctxt.host = host;