%n ssh %v 1.2.14 %c * %l * %b * %d * %f * %t ssh-1.2.14.tgz %w Nonfree %% %setup patch -u -p1 <<'ENDPATCH' diff -ru2N ssh-1.2.14/Makefile.in ssh-MCC/Makefile.in --- ssh-1.2.14/Makefile.in Thu Jun 6 14:47:08 1996 +++ ssh-MCC/Makefile.in Sun Sep 22 10:32:27 1996 @@ -111,8 +111,8 @@ CC = @CC@ -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ +CFLAGS = -O6 -fomit-frame-pointer +LDFLAGS = -Wl,-warn-common DEFS = @DEFS@ -LIBS = @LIBS@ +LIBS = LIBOBJS = @LIBOBJS@ CONFOBJS = @CONFOBJS@ @@ -347,5 +347,18 @@ # bound to a non-privileged port). Also, password authentication may # not be available if non-root and using shadow passwords. -install: $(PROGRAMS) make-dirs generate-host-key install-configs +install: $(PROGRAMS) + install -s -m 4555 ssh $(bindir) + ln -f $(bindir)/ssh $(bindir)/slogin + install -s -m 555 ssh-keygen ssh-agent ssh-add scp ssh-askpass \ + $(bindir) + install -s -m 555 sshd make-ssh-known-hosts $(sbindir) + for p in ssh-keygen.1 ssh-agent.1 ssh-add.1 scp.1 \ + ssh.1 make-ssh-known-hosts.1;do \ + install -m 444 $$p $(man1dir)/$$p;\ + gzip -9f $(man1dir)/$$p;done + install -m 444 sshd.8 $(man8dir) + gzip -9f $(man8dir)/sshd.8 + +dummy: $(PROGRAMS) make-dirs generate-host-key install-configs $(INSTALL_PROGRAM) -o root -m 04711 ssh $(install_prefix)$(bindir)/ssh -if test "`echo ssh | sed '$(transform)'`" '!=' ssh; then \ diff -ru2N ssh-1.2.14/auth-rsa.c ssh-MCC/auth-rsa.c --- ssh-1.2.14/auth-rsa.c Thu Jun 6 14:47:06 1996 +++ ssh-MCC/auth-rsa.c Sun Sep 22 10:31:17 1996 @@ -144,5 +144,6 @@ successful. This may exit if there is a serious protocol violation. */ -int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state) +int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state, + int strict_modes) { char line[8192]; @@ -154,6 +155,33 @@ struct stat st; - /* Open the file containing the authorized keys. */ + /* Check permissions & owner of user's home directory */ + if (strict_modes && !userfile_check_owner_permissions(pw, pw->pw_dir)) + { + log("Rsa authentication refused for %.100s: bad modes for %.200s", + pw->pw_name, pw->pw_dir); + packet_send_debug("Bad file modes for %.200s", pw->pw_dir); + return 0; + } + /* Check permissions & owner of user's .ssh directory */ + sprintf(line, "%.500s/%.100s", pw->pw_dir, SSH_USER_DIR); + if (strict_modes && !userfile_check_owner_permissions(pw, line)) + { + log("Rsa authentication refused for %.100s: bad modes for %.200s", + pw->pw_name, line); + packet_send_debug("Bad file modes for %.200s", line); + return 0; + } + + /* Check permissions & owner of user's authorized keys file */ sprintf(line, "%.500s/%.100s", pw->pw_dir, SSH_USER_PERMITTED_KEYS); + if (strict_modes && !userfile_check_owner_permissions(pw, line)) + { + log("Rsa authentication refused for %.100s: bad modes for %.200s", + pw->pw_name, line); + packet_send_debug("Bad file modes for %.200s", line); + return 0; + } + + /* Open the file containing the authorized keys. */ if (userfile_stat(pw->pw_uid, line, &st) < 0) diff -ru2N ssh-1.2.14/newchannels.c ssh-MCC/newchannels.c --- ssh-1.2.14/newchannels.c Thu Jun 6 14:47:06 1996 +++ ssh-MCC/newchannels.c Sun Sep 22 10:31:56 1996 @@ -139,4 +139,6 @@ int listening_port; /* port being listened for forwards */ char *remote_name; + + int is_x_connection; } Channel; @@ -162,4 +164,7 @@ static char *channel_forwarded_auth_socket_name = NULL; +/* Agent forwarding socket directory name */ +static char *channel_forwarded_auth_socket_dir_name = NULL; + /* Saved X11 authentication protocol name. */ char *x11_saved_proto = NULL; @@ -266,4 +271,5 @@ channels[i].status_flags = 0; channels[i].local_id = i; + channels[i].is_x_connection = 0; channels_used++; debug("Allocated channel %d.\n", i); @@ -431,4 +437,9 @@ debug("Channel %d receives input eof.", ch->local_id); ch->status_flags |= EPSILON_R; + if (ch->is_x_connection) + { + debug("X problem fix: close the other direction."); + channel_close_input(ch); + } channel_check_termination(ch); } @@ -665,4 +676,5 @@ newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, xstrdup(buf)); + channels[newch].is_x_connection = 1; packet_start(SSH_SMSG_X11_OPEN); packet_put_int(newch); @@ -1545,4 +1557,5 @@ else newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host); + channels[newch].is_x_connection = 1; channels[newch].remote_id = remote_channel; @@ -1646,4 +1659,21 @@ } +/* Called on exit, tries to remove authentication socket and per-user + socket directory */ + +void auth_delete_socket(void *context) +{ + if (channel_forwarded_auth_socket_name) + { + remove(channel_forwarded_auth_socket_name); + xfree(channel_forwarded_auth_socket_name); + } + if (channel_forwarded_auth_socket_dir_name) + { + rmdir(channel_forwarded_auth_socket_dir_name); + xfree(channel_forwarded_auth_socket_dir_name); + } +} + /* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server. This starts forwarding authentication requests. */ @@ -1651,5 +1681,5 @@ void auth_input_request_forwarding(struct passwd *pw) { - int pfd = get_permanent_fd(pw->pw_shell); + int ret, pfd = get_permanent_fd(pw->pw_shell); if (pfd < 0) @@ -1657,13 +1687,37 @@ int sock, newch; struct sockaddr_un sunaddr; - + struct stat st; + if (auth_get_socket_name() != NULL) fatal("Protocol error: authentication forwarding requested twice."); - - /* Allocate a buffer for the socket name, and format the name. */ + + /* Allocate a buffer for the socket name, and format the name. + And directory name. */ channel_forwarded_auth_socket_name = xmalloc(100); - sprintf(channel_forwarded_auth_socket_name, SSH_AGENT_SOCKET, - (int)getpid()); - + channel_forwarded_auth_socket_dir_name = xmalloc(100); + sprintf(channel_forwarded_auth_socket_dir_name, + SSH_AGENT_SOCKET_DIR, pw->pw_name); + sprintf(channel_forwarded_auth_socket_name, + SSH_AGENT_SOCKET_DIR"/"SSH_AGENT_SOCKET, + pw->pw_name, (int)getpid()); + + /* Register the cleanup function before making the directory */ + fatal_add_cleanup(&auth_delete_socket, NULL); + + /* Check that the per-user socket directory either doesn't exist + or has good modes */ + + ret = stat(channel_forwarded_auth_socket_dir_name, &st); + if (ret == -1 && errno != ENOENT) + packet_disconnect("stat: %.100s", strerror(errno)); + else + userfile_mkdir(pw->pw_uid, channel_forwarded_auth_socket_dir_name, S_IRWXU); + + if (ret == 0 && !userfile_check_owner_permissions(pw, channel_forwarded_auth_socket_dir_name)) + { + packet_disconnect("Bad modes for directory \'%s\'\n", + channel_forwarded_auth_socket_dir_name); + } + /* Create the socket. */ sock = socket(AF_UNIX, SOCK_STREAM, 0); diff -ru2N ssh-1.2.14/ssh-agent.c ssh-MCC/ssh-agent.c --- ssh-1.2.14/ssh-agent.c Thu Jun 6 14:47:04 1996 +++ ssh-MCC/ssh-agent.c Sun Sep 22 10:31:56 1996 @@ -63,4 +63,5 @@ #include "getput.h" #include "mpaux.h" +#include "userfile.h" typedef struct @@ -534,4 +535,5 @@ int parent_pid = -1; +char socket_dir_name[1024]; char socket_name[1024]; @@ -541,4 +543,5 @@ { remove(socket_name); + rmdir(socket_dir_name); /* printf("Parent has died - Authentication agent exiting.\n"); */ exit(1); @@ -551,4 +554,5 @@ { remove(socket_name); + rmdir(socket_dir_name); /* fprintf(stderr, "Received signal %d - Auth. agent exiting.\n", sig); */ exit(1); @@ -562,7 +566,9 @@ int sock; struct sockaddr_un sunaddr; - + struct passwd *pw; + struct stat st; + int sockets[2], i; - int *dups; + int *dups, ret; if (ac < 2) @@ -577,8 +583,42 @@ { /* The agent uses SSH_AUTHENTICATION_SOCKET. */ - + parent_pid = getpid(); + pw = getpwuid(getuid()); + + sprintf(socket_dir_name, SSH_AGENT_SOCKET_DIR, pw->pw_name); + + /* Check that the per-user socket directory either doesn't exist + or has good modes */ - sprintf(socket_name, SSH_AGENT_SOCKET, parent_pid); + ret = stat(socket_dir_name, &st); + if (ret == -1 && errno != ENOENT) + { + perror("stat"); + exit(1); + } + else + userfile_mkdir(pw->pw_uid, socket_dir_name, S_IRWXU); + + if (ret == 0 && !userfile_check_owner_permissions(pw, socket_dir_name)) + { + fprintf(stderr, "Bad modes for directory \'%s\'\n", socket_dir_name); + exit(1); + } + + sprintf(socket_name, + SSH_AGENT_SOCKET_DIR"/"SSH_AGENT_SOCKET, + pw->pw_name, (int)getpid()); + + /* Check that socket doesn't exist */ + + ret = stat(socket_name, &st); + if (ret != -1 && errno != ENOENT) + { + fprintf(stderr, + "\'%s\' already exists (ssh-agent already running?)\n", + socket_name); + exit(1); + } /* Fork, and have the parent execute the command. The child continues as diff -ru2N ssh-1.2.14/ssh.h ssh-MCC/ssh.h --- ssh-1.2.14/ssh.h Thu Jun 6 14:47:01 1996 +++ ssh-MCC/ssh.h Sun Sep 22 10:31:55 1996 @@ -188,13 +188,19 @@ on some systems, commonly used shells close all open file descriptors. To make the agent usable on those systems, configure checks whether - the shells close all descriptors, and if so, defines AGENT_USES_SOCKET. - That socket is an unix-domain socket and will be stored with this name - in the user\'s home directory. The socket must not be accessible by - anyone but the user him/herself. The number at the end of the name - is the pid of the agent or the forwarding daemon. Note that this - socket is stored in /tmp, which is supposedly on the local machine. If - this were in the user\'s home directory, the daemon (running as root) - might not be able to create and chown the file to the user\'s uid. */ -#define SSH_AGENT_SOCKET "/tmp/ssh_agent.%d" + the shells close all descriptors, and if so, uses a socket instead. + That socket is an unix-domain socket and must not be accessible by + anyone but the user him/herself. A directory \'ssh-agent-\' + is created under /tmp, which is supposedly on the local machine, + and socket is created under the directory. On some systems, sockets\' + protections are not adequately checked, so this mode 700 per-user + directory is needed. If socket were in the user\'s home directory, + the daemon (running as root) might not be able to create and chown + the file to the user\'s uid. + + SSH_AGENT_SOCKET_DIR can be changed to something else ("/tmp/.ssh/ssh-%s" + for example), but only the last directory in the path will be + dynamically created and deleted by sshd and ssh-agent. */ +#define SSH_AGENT_SOCKET_DIR "/tmp/ssh-%.50s" +#define SSH_AGENT_SOCKET "agent-socket-%d" /* Name of the environment variable containing the authentication fd. */ @@ -342,5 +348,6 @@ 0 if the client could not be authenticated, and 1 if authentication was successful. This may exit if there is a serious protocol violation. */ -int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state); +int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state, + int strict_modes); /* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer diff -ru2N ssh-1.2.14/sshd.c ssh-MCC/sshd.c --- ssh-1.2.14/sshd.c Thu Jun 6 14:47:07 1996 +++ ssh-MCC/sshd.c Sun Sep 22 10:31:55 1996 @@ -969,4 +969,7 @@ do_connection(get_remote_port() < 1024); + /* Try to remove authentication socket and directory */ + auth_delete_socket(NULL); + /* The connection has been terminated. */ log("Closing connection to %.100s", get_remote_ipaddr()); @@ -1424,5 +1427,6 @@ mpz_init(&n); packet_get_mp_int(&n); - if (auth_rsa(pw, &n, &sensitive_data.random_state)) + if (auth_rsa(pw, &n, &sensitive_data.random_state, + options.strict_modes)) { /* Successful authentication. */ diff -ru2N ssh-1.2.14/userfile.c ssh-MCC/userfile.c --- ssh-1.2.14/userfile.c Thu Jun 6 14:47:06 1996 +++ ssh-MCC/userfile.c Sun Sep 22 10:24:46 1996 @@ -1020,2 +1020,13 @@ } } +int userfile_check_owner_permissions(struct passwd *pw, const char *path) +{ + struct stat st; + if (userfile_stat(pw->pw_uid, path, &st) < 0) + return 0; + if ((st.st_uid != 0 && st.st_uid != pw->pw_uid) || + (st.st_mode & 022) != 0) + return 0; + else + return 1; +} diff -ru2N ssh-1.2.14/userfile.h ssh-MCC/userfile.h --- ssh-1.2.14/userfile.h Thu Jun 6 14:47:01 1996 +++ ssh-MCC/userfile.h Sun Sep 22 10:24:46 1996 @@ -103,3 +103,7 @@ int userfile_pclose(UserFile uf); +/* Check owner and permissions of a given file/directory. + Permissions ----w--w- must not exist and owner must be either + pw->pw_uid or root. Return value: 0 = not ok, 1 = ok */ +int userfile_check_owner_permissions(struct passwd *pw, const char *path); #endif /* USERFILE_H */ ENDPATCH ./configure --prefix=/usr --with-etcdir=/etc/ssh make * make install %%