summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'session.c')
-rw-r--r--session.c463
1 files changed, 247 insertions, 216 deletions
diff --git a/session.c b/session.c
index 2134d917a..e4934a415 100644
--- a/session.c
+++ b/session.c
@@ -33,7 +33,7 @@
33 */ 33 */
34 34
35#include "includes.h" 35#include "includes.h"
36RCSID("$OpenBSD: session.c,v 1.126 2002/02/14 23:28:00 markus Exp $"); 36RCSID("$OpenBSD: session.c,v 1.127 2002/02/15 23:11:26 markus Exp $");
37 37
38#include "ssh.h" 38#include "ssh.h"
39#include "ssh1.h" 39#include "ssh1.h"
@@ -657,6 +657,7 @@ do_exec(Session *s, const char *command)
657 original_command = NULL; 657 original_command = NULL;
658} 658}
659 659
660
660/* administrative, login(1)-like work */ 661/* administrative, login(1)-like work */
661void 662void
662do_login(Session *s, const char *command) 663do_login(Session *s, const char *command)
@@ -677,7 +678,7 @@ do_login(Session *s, const char *command)
677 if (packet_connection_is_on_socket()) { 678 if (packet_connection_is_on_socket()) {
678 fromlen = sizeof(from); 679 fromlen = sizeof(from);
679 if (getpeername(packet_get_connection_in(), 680 if (getpeername(packet_get_connection_in(),
680 (struct sockaddr *) & from, &fromlen) < 0) { 681 (struct sockaddr *) & from, &fromlen) < 0) {
681 debug("getpeername: %.100s", strerror(errno)); 682 debug("getpeername: %.100s", strerror(errno));
682 fatal_cleanup(); 683 fatal_cleanup();
683 } 684 }
@@ -883,134 +884,13 @@ void copy_environment(char **source, char ***env, u_int *envsize)
883 } 884 }
884} 885}
885 886
886/* 887static char **
887 * Performs common processing for the child, such as setting up the 888do_setup_env(Session *s, const char *shell)
888 * environment, closing extra file descriptors, setting the user and group
889 * ids, and executing the command or shell.
890 */
891void
892do_child(Session *s, const char *command)
893{ 889{
894 const char *shell, *hostname = NULL, *cp = NULL;
895 struct passwd *pw = s->pw;
896 char buf[256]; 890 char buf[256];
897 char cmd[1024]; 891 u_int i, envsize;
898 FILE *f = NULL;
899 u_int envsize, i;
900 char **env; 892 char **env;
901 extern char **environ; 893 struct passwd *pw = s->pw;
902 struct stat st;
903 char *argv[10];
904 int do_xauth;
905
906 do_xauth =
907 s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
908
909 /* remove hostkey from the child's memory */
910 destroy_sensitive_data();
911
912 /* login(1) is only called if we execute the login shell */
913 if (options.use_login && command != NULL)
914 options.use_login = 0;
915
916#if !defined(HAVE_OSF_SIA)
917 if (!options.use_login) {
918# ifdef HAVE_LOGIN_CAP
919 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
920 f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
921 _PATH_NOLOGIN), "r");
922# else /* HAVE_LOGIN_CAP */
923 if (pw->pw_uid)
924 f = fopen(_PATH_NOLOGIN, "r");
925# endif /* HAVE_LOGIN_CAP */
926 if (f) {
927 /* /etc/nologin exists. Print its contents and exit. */
928 while (fgets(buf, sizeof(buf), f))
929 fputs(buf, stderr);
930 fclose(f);
931 exit(254);
932 }
933 }
934#endif /* HAVE_OSF_SIA */
935
936 /* Set login name, uid, gid, and groups. */
937 /* Login(1) does this as well, and it needs uid 0 for the "-h"
938 switch, so we let login(1) to this for us. */
939 if (!options.use_login) {
940#ifdef HAVE_OSF_SIA
941 session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty);
942 if (!check_quietlogin(s, command))
943 do_motd();
944#else /* HAVE_OSF_SIA */
945#ifdef HAVE_CYGWIN
946 if (is_winnt) {
947#else
948 if (getuid() == 0 || geteuid() == 0) {
949#endif
950# ifdef HAVE_GETUSERATTR
951 set_limits_from_userattr(pw->pw_name);
952# endif /* HAVE_GETUSERATTR */
953# ifdef HAVE_LOGIN_CAP
954 if (setusercontext(lc, pw, pw->pw_uid,
955 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
956 perror("unable to set user context");
957 exit(1);
958 }
959# else /* HAVE_LOGIN_CAP */
960#if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
961 /* Sets login uid for accounting */
962 if (getluid() == -1 && setluid(pw->pw_uid) == -1)
963 error("setluid: %s", strerror(errno));
964#endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
965
966 if (setlogin(pw->pw_name) < 0)
967 error("setlogin failed: %s", strerror(errno));
968 if (setgid(pw->pw_gid) < 0) {
969 perror("setgid");
970 exit(1);
971 }
972 /* Initialize the group list. */
973 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
974 perror("initgroups");
975 exit(1);
976 }
977 endgrent();
978# ifdef USE_PAM
979 /*
980 * PAM credentials may take the form of
981 * supplementary groups. These will have been
982 * wiped by the above initgroups() call.
983 * Reestablish them here.
984 */
985 do_pam_setcred(0);
986# endif /* USE_PAM */
987# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
988 irix_setusercontext(pw);
989# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
990#ifdef _AIX
991 aix_usrinfo(s)
992#endif
993
994 /* Permanently switch to the desired uid. */
995 permanently_set_uid(pw);
996# endif /* HAVE_LOGIN_CAP */
997 }
998#endif /* HAVE_OSF_SIA */
999
1000#ifdef HAVE_CYGWIN
1001 if (is_winnt)
1002#endif
1003 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1004 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1005 }
1006 /*
1007 * Get the shell from the password data. An empty shell field is
1008 * legal, and means /bin/sh.
1009 */
1010 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1011#ifdef HAVE_LOGIN_CAP
1012 shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1013#endif
1014 894
1015 /* Initialize the environment. */ 895 /* Initialize the environment. */
1016 envsize = 100; 896 envsize = 100;
@@ -1060,7 +940,7 @@ do_child(Session *s, const char *command)
1060 while (custom_environment) { 940 while (custom_environment) {
1061 struct envstring *ce = custom_environment; 941 struct envstring *ce = custom_environment;
1062 char *s = ce->s; 942 char *s = ce->s;
1063 int i; 943
1064 for (i = 0; s[i] != '=' && s[i]; i++) 944 for (i = 0; s[i] != '=' && s[i]; i++)
1065 ; 945 ;
1066 if (s[i] == '=') { 946 if (s[i] == '=') {
@@ -1074,7 +954,7 @@ do_child(Session *s, const char *command)
1074 } 954 }
1075 955
1076 snprintf(buf, sizeof buf, "%.50s %d %d", 956 snprintf(buf, sizeof buf, "%.50s %d %d",
1077 get_remote_ipaddr(), get_remote_port(), get_local_port()); 957 get_remote_ipaddr(), get_remote_port(), get_local_port());
1078 child_set_env(&env, &envsize, "SSH_CLIENT", buf); 958 child_set_env(&env, &envsize, "SSH_CLIENT", buf);
1079 959
1080 if (s->ttyfd != -1) 960 if (s->ttyfd != -1)
@@ -1125,6 +1005,206 @@ do_child(Session *s, const char *command)
1125 for (i = 0; env[i]; i++) 1005 for (i = 0; env[i]; i++)
1126 fprintf(stderr, " %.200s\n", env[i]); 1006 fprintf(stderr, " %.200s\n", env[i]);
1127 } 1007 }
1008 return env;
1009}
1010
1011/*
1012 * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found
1013 * first in this order).
1014 */
1015static void
1016do_rc_files(Session *s, const char *shell)
1017{
1018 FILE *f = NULL;
1019 char cmd[1024];
1020 int do_xauth;
1021 struct stat st;
1022
1023 do_xauth =
1024 s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
1025
1026 /* ignore _PATH_SSH_USER_RC for subsystems */
1027 if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1028 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1029 shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1030 if (debug_flag)
1031 fprintf(stderr, "Running %s\n", cmd);
1032 f = popen(cmd, "w");
1033 if (f) {
1034 if (do_xauth)
1035 fprintf(f, "%s %s\n", s->auth_proto,
1036 s->auth_data);
1037 pclose(f);
1038 } else
1039 fprintf(stderr, "Could not run %s\n",
1040 _PATH_SSH_USER_RC);
1041 } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1042 if (debug_flag)
1043 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1044 _PATH_SSH_SYSTEM_RC);
1045 f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1046 if (f) {
1047 if (do_xauth)
1048 fprintf(f, "%s %s\n", s->auth_proto,
1049 s->auth_data);
1050 pclose(f);
1051 } else
1052 fprintf(stderr, "Could not run %s\n",
1053 _PATH_SSH_SYSTEM_RC);
1054 } else if (do_xauth && options.xauth_location != NULL) {
1055 /* Add authority data to .Xauthority if appropriate. */
1056 if (debug_flag) {
1057 fprintf(stderr,
1058 "Running %.100s add "
1059 "%.100s %.100s %.100s\n",
1060 options.xauth_location, s->auth_display,
1061 s->auth_proto, s->auth_data);
1062 }
1063 snprintf(cmd, sizeof cmd, "%s -q -",
1064 options.xauth_location);
1065 f = popen(cmd, "w");
1066 if (f) {
1067 fprintf(f, "add %s %s %s\n",
1068 s->auth_display, s->auth_proto,
1069 s->auth_data);
1070 pclose(f);
1071 } else {
1072 fprintf(stderr, "Could not run %s\n",
1073 cmd);
1074 }
1075 }
1076}
1077
1078static void
1079do_nologin(struct passwd *pw)
1080{
1081 FILE *f = NULL;
1082 char buf[1024];
1083
1084#ifdef HAVE_LOGIN_CAP
1085 if (!login_getcapbool(lc, "ignorenologin", 0) && pw->pw_uid)
1086 f = fopen(login_getcapstr(lc, "nologin", _PATH_NOLOGIN,
1087 _PATH_NOLOGIN), "r");
1088#else
1089 if (pw->pw_uid)
1090 f = fopen(_PATH_NOLOGIN, "r");
1091#endif
1092 if (f) {
1093 /* /etc/nologin exists. Print its contents and exit. */
1094 while (fgets(buf, sizeof(buf), f))
1095 fputs(buf, stderr);
1096 fclose(f);
1097 exit(254);
1098 }
1099}
1100
1101/* Set login name, uid, gid, and groups. */
1102static void
1103do_setusercontext(struct passwd *pw)
1104{
1105#ifdef HAVE_CYGWIN
1106 if (iswinnt) {
1107#else /* HAVE_CYGWIN */
1108 if (getuid() == 0 || geteuid() == 0) {
1109#endif /* HAVE_CYGWIN */
1110#ifdef HAVE_GETUSERATTR
1111 set_limits_from_userattr(pw->pw_name);
1112#endif /* HAVE_GETUSERATTR */
1113#ifdef HAVE_LOGIN_CAP
1114 if (setusercontext(lc, pw, pw->pw_uid,
1115 (LOGIN_SETALL & ~LOGIN_SETPATH)) < 0) {
1116 perror("unable to set user context");
1117 exit(1);
1118 }
1119#else
1120# if defined(HAVE_GETLUID) && defined(HAVE_SETLUID)
1121 /* Sets login uid for accounting */
1122 if (getluid() == -1 && setluid(pw->pw_uid) == -1)
1123 error("setluid: %s", strerror(errno));
1124# endif /* defined(HAVE_GETLUID) && defined(HAVE_SETLUID) */
1125
1126 if (setlogin(pw->pw_name) < 0)
1127 error("setlogin failed: %s", strerror(errno));
1128 if (setgid(pw->pw_gid) < 0) {
1129 perror("setgid");
1130 exit(1);
1131 }
1132 /* Initialize the group list. */
1133 if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
1134 perror("initgroups");
1135 exit(1);
1136 }
1137 endgrent();
1138# ifdef USE_PAM
1139 /*
1140 * PAM credentials may take the form of supplementary groups.
1141 * These will have been wiped by the above initgroups() call.
1142 * Reestablish them here.
1143 */
1144 do_pam_setcred(0);
1145# endif /* USE_PAM */
1146# if defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY)
1147 irix_setusercontext(pw);
1148# endif /* defined(WITH_IRIX_PROJECT) || defined(WITH_IRIX_JOBS) || defined(WITH_IRIX_ARRAY) */
1149#ifdef _AIX
1150 aix_usrinfo(s)
1151#endif
1152 /* Permanently switch to the desired uid. */
1153 permanently_set_uid(pw);
1154#endif
1155 }
1156 if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
1157 fatal("Failed to set uids to %u.", (u_int) pw->pw_uid);
1158}
1159
1160/*
1161 * Performs common processing for the child, such as setting up the
1162 * environment, closing extra file descriptors, setting the user and group
1163 * ids, and executing the command or shell.
1164 */
1165void
1166do_child(Session *s, const char *command)
1167{
1168 extern char **environ;
1169 char **env;
1170 char *argv[10];
1171 const char *shell, *shell0, *hostname = NULL;
1172 struct passwd *pw = s->pw;
1173 u_int i;
1174
1175 /* remove hostkey from the child's memory */
1176 destroy_sensitive_data();
1177
1178 /* login(1) is only called if we execute the login shell */
1179 if (options.use_login && command != NULL)
1180 options.use_login = 0;
1181
1182 /*
1183 * Login(1) does this as well, and it needs uid 0 for the "-h"
1184 * switch, so we let login(1) to this for us.
1185 */
1186 if (!options.use_login) {
1187#ifdef HAVE_OSF_SIA
1188 session_setup_sia(pw->pw_name, s->ttyfd == -1 ? NULL : s->tty);
1189 if (!check_quietlogin(s, command))
1190 do_motd();
1191#else /* HAVE_OSF_SIA */
1192 do_nologin(pw);
1193 do_setusercontext(pw);
1194#endif /* HAVE_OSF_SIA */
1195 }
1196
1197 /*
1198 * Get the shell from the password data. An empty shell field is
1199 * legal, and means /bin/sh.
1200 */
1201 shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
1202#ifdef HAVE_LOGIN_CAP
1203 shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
1204#endif
1205
1206 env = do_setup_env(s, shell);
1207
1128 /* we have to stash the hostname before we close our socket. */ 1208 /* we have to stash the hostname before we close our socket. */
1129 if (options.use_login) 1209 if (options.use_login)
1130 hostname = get_remote_name_or_ip(utmp_len, 1210 hostname = get_remote_name_or_ip(utmp_len,
@@ -1192,114 +1272,65 @@ do_child(Session *s, const char *command)
1192#endif 1272#endif
1193 } 1273 }
1194 1274
1195 /* 1275 if (!options.use_login)
1196 * Run $HOME/.ssh/rc, /etc/ssh/sshrc, or xauth (whichever is found 1276 do_rc_files(s, shell);
1197 * first in this order).
1198 */
1199 if (!options.use_login) {
1200 /* ignore _PATH_SSH_USER_RC for subsystems */
1201 if (!s->is_subsystem && (stat(_PATH_SSH_USER_RC, &st) >= 0)) {
1202 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1203 shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1204 if (debug_flag)
1205 fprintf(stderr, "Running %s\n", cmd);
1206 f = popen(cmd, "w");
1207 if (f) {
1208 if (do_xauth)
1209 fprintf(f, "%s %s\n", s->auth_proto,
1210 s->auth_data);
1211 pclose(f);
1212 } else
1213 fprintf(stderr, "Could not run %s\n",
1214 _PATH_SSH_USER_RC);
1215 } else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
1216 if (debug_flag)
1217 fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
1218 _PATH_SSH_SYSTEM_RC);
1219 f = popen(_PATH_BSHELL " " _PATH_SSH_SYSTEM_RC, "w");
1220 if (f) {
1221 if (do_xauth)
1222 fprintf(f, "%s %s\n", s->auth_proto,
1223 s->auth_data);
1224 pclose(f);
1225 } else
1226 fprintf(stderr, "Could not run %s\n",
1227 _PATH_SSH_SYSTEM_RC);
1228 } else if (do_xauth && options.xauth_location != NULL) {
1229 /* Add authority data to .Xauthority if appropriate. */
1230 if (debug_flag) {
1231 fprintf(stderr,
1232 "Running %.100s add "
1233 "%.100s %.100s %.100s\n",
1234 options.xauth_location, s->auth_display,
1235 s->auth_proto, s->auth_data);
1236 }
1237 snprintf(cmd, sizeof cmd, "%s -q -",
1238 options.xauth_location);
1239 f = popen(cmd, "w");
1240 if (f) {
1241 fprintf(f, "add %s %s %s\n",
1242 s->auth_display, s->auth_proto,
1243 s->auth_data);
1244 pclose(f);
1245 } else {
1246 fprintf(stderr, "Could not run %s\n",
1247 cmd);
1248 }
1249 }
1250 /* Get the last component of the shell name. */
1251 cp = strrchr(shell, '/');
1252 if (cp)
1253 cp++;
1254 else
1255 cp = shell;
1256 }
1257 1277
1258 /* restore SIGPIPE for child */ 1278 /* restore SIGPIPE for child */
1259 signal(SIGPIPE, SIG_DFL); 1279 signal(SIGPIPE, SIG_DFL);
1260 1280
1281 if (options.use_login) {
1282 /* Launch login(1). */
1283
1284 execl(LOGIN_PROGRAM, "login", "-h", hostname,
1285#ifdef LOGIN_NEEDS_TERM
1286 (s->term ? s->term : "unknown"),
1287#endif /* LOGIN_NEEDS_TERM */
1288 "-p", "-f", "--", pw->pw_name, (char *)NULL);
1289
1290 /* Login couldn't be executed, die. */
1291
1292 perror("login");
1293 exit(1);
1294 }
1295
1296 /* Get the last component of the shell name. */
1297 if ((shell0 = strrchr(shell, '/')) != NULL)
1298 shell0++;
1299 else
1300 shell0 = shell;
1301
1261 /* 1302 /*
1262 * If we have no command, execute the shell. In this case, the shell 1303 * If we have no command, execute the shell. In this case, the shell
1263 * name to be passed in argv[0] is preceded by '-' to indicate that 1304 * name to be passed in argv[0] is preceded by '-' to indicate that
1264 * this is a login shell. 1305 * this is a login shell.
1265 */ 1306 */
1266 if (!command) { 1307 if (!command) {
1267 if (!options.use_login) { 1308 char argv0[256];
1268 char buf[256];
1269 1309
1270 /* Start the shell. Set initial character to '-'. */ 1310 /* Start the shell. Set initial character to '-'. */
1271 buf[0] = '-'; 1311 argv0[0] = '-';
1272 strlcpy(buf + 1, cp, sizeof(buf) - 1);
1273 1312
1274 /* Execute the shell. */ 1313 if (strlcpy(argv0 + 1, shell0, sizeof(argv0) - 1)
1275 argv[0] = buf; 1314 >= sizeof(argv0) - 1) {
1276 argv[1] = NULL; 1315 errno = EINVAL;
1277 execve(shell, argv, env);
1278
1279 /* Executing the shell failed. */
1280 perror(shell); 1316 perror(shell);
1281 exit(1); 1317 exit(1);
1318 }
1282 1319
1283 } else { 1320 /* Execute the shell. */
1284 /* Launch login(1). */ 1321 argv[0] = argv0;
1285 1322 argv[1] = NULL;
1286 execl(LOGIN_PROGRAM, "login", "-h", hostname, 1323 execve(shell, argv, env);
1287#ifdef LOGIN_NEEDS_TERM
1288 s->term? s->term : "unknown",
1289#endif
1290 "-p", "-f", "--", pw->pw_name, (char *)NULL);
1291
1292 /* Login couldn't be executed, die. */
1293 1324
1294 perror("login"); 1325 /* Executing the shell failed. */
1295 exit(1); 1326 perror(shell);
1296 } 1327 exit(1);
1297 } 1328 }
1298 /* 1329 /*
1299 * Execute the command using the user's shell. This uses the -c 1330 * Execute the command using the user's shell. This uses the -c
1300 * option to execute the command. 1331 * option to execute the command.
1301 */ 1332 */
1302 argv[0] = (char *) cp; 1333 argv[0] = (char *) shell0;
1303 argv[1] = "-c"; 1334 argv[1] = "-c";
1304 argv[2] = (char *) command; 1335 argv[2] = (char *) command;
1305 argv[3] = NULL; 1336 argv[3] = NULL;