00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "includes.h"
00017 RCSID("$OpenBSD: auth-rhosts.c,v 1.33 2005/07/17 07:17:54 djm Exp $");
00018
00019 #include "packet.h"
00020 #include "uidswap.h"
00021 #include "pathnames.h"
00022 #include "log.h"
00023 #include "servconf.h"
00024 #include "canohost.h"
00025 #include "auth.h"
00026
00027
00028 extern ServerOptions options;
00029 extern int use_privsep;
00030
00031
00032
00033
00034
00035
00036
00037 static int
00038 check_rhosts_file(const char *filename, const char *hostname,
00039 const char *ipaddr, const char *client_user,
00040 const char *server_user)
00041 {
00042 FILE *f;
00043 char buf[1024];
00044
00045
00046 f = fopen(filename, "r");
00047 if (!f)
00048 return 0;
00049
00050 while (fgets(buf, sizeof(buf), f)) {
00051
00052 char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
00053 int negated;
00054
00055 for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
00056 ;
00057 if (*cp == '#' || *cp == '\n' || !*cp)
00058 continue;
00059
00060
00061
00062
00063
00064 if (strncmp(cp, "NO_PLUS", 7) == 0)
00065 continue;
00066
00067
00068
00069
00070
00071 switch (sscanf(buf, "%1023s %1023s %1023s", hostbuf, userbuf,
00072 dummy)) {
00073 case 0:
00074 auth_debug_add("Found empty line in %.100s.", filename);
00075 continue;
00076 case 1:
00077
00078 strlcpy(userbuf, server_user, sizeof(userbuf));
00079 break;
00080 case 2:
00081
00082 break;
00083 case 3:
00084 auth_debug_add("Found garbage in %.100s.", filename);
00085 continue;
00086 default:
00087
00088 continue;
00089 }
00090
00091 host = hostbuf;
00092 user = userbuf;
00093 negated = 0;
00094
00095
00096 if (host[0] == '-') {
00097 negated = 1;
00098 host++;
00099 } else if (host[0] == '+')
00100 host++;
00101
00102 if (user[0] == '-') {
00103 negated = 1;
00104 user++;
00105 } else if (user[0] == '+')
00106 user++;
00107
00108
00109 if (!host[0] || !user[0]) {
00110
00111 auth_debug_add("Ignoring wild host/user names in %.100s.",
00112 filename);
00113 continue;
00114 }
00115
00116 if (host[0] == '@') {
00117 if (!innetgr(host + 1, hostname, NULL, NULL) &&
00118 !innetgr(host + 1, ipaddr, NULL, NULL))
00119 continue;
00120 } else if (strcasecmp(host, hostname) && strcmp(host, ipaddr) != 0)
00121 continue;
00122
00123
00124 if (user[0] == '@') {
00125 if (!innetgr(user + 1, NULL, client_user, NULL))
00126 continue;
00127 } else if (strcmp(user, client_user) != 0)
00128 continue;
00129
00130
00131 fclose(f);
00132
00133
00134 if (negated) {
00135 auth_debug_add("Matched negative entry in %.100s.",
00136 filename);
00137 return 0;
00138 }
00139
00140 return 1;
00141 }
00142
00143
00144 fclose(f);
00145 return 0;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154 int
00155 auth_rhosts(struct passwd *pw, const char *client_user)
00156 {
00157 const char *hostname, *ipaddr;
00158
00159 hostname = get_canonical_hostname(options.use_dns);
00160 ipaddr = get_remote_ipaddr();
00161 return auth_rhosts2(pw, client_user, hostname, ipaddr);
00162 }
00163
00164 static int
00165 auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostname,
00166 const char *ipaddr)
00167 {
00168 char buf[1024];
00169 struct stat st;
00170 static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
00171 u_int rhosts_file_index;
00172
00173 debug2("auth_rhosts2: clientuser %s hostname %s ipaddr %s",
00174 client_user, hostname, ipaddr);
00175
00176
00177 temporarily_use_uid(pw);
00178
00179
00180
00181
00182
00183 for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
00184 rhosts_file_index++) {
00185
00186 snprintf(buf, sizeof buf, "%.500s/%.100s",
00187 pw->pw_dir, rhosts_files[rhosts_file_index]);
00188 if (stat(buf, &st) >= 0)
00189 break;
00190 }
00191
00192 restore_uid();
00193
00194
00195 if (!rhosts_files[rhosts_file_index] &&
00196 stat(_PATH_RHOSTS_EQUIV, &st) < 0 &&
00197 stat(_PATH_SSH_HOSTS_EQUIV, &st) < 0)
00198 return 0;
00199
00200
00201 if (pw->pw_uid != 0) {
00202 if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
00203 client_user, pw->pw_name)) {
00204 auth_debug_add("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
00205 hostname, ipaddr);
00206 return 1;
00207 }
00208 if (check_rhosts_file(_PATH_SSH_HOSTS_EQUIV, hostname, ipaddr,
00209 client_user, pw->pw_name)) {
00210 auth_debug_add("Accepted for %.100s [%.100s] by %.100s.",
00211 hostname, ipaddr, _PATH_SSH_HOSTS_EQUIV);
00212 return 1;
00213 }
00214 }
00215
00216
00217
00218
00219 if (stat(pw->pw_dir, &st) < 0) {
00220 logit("Rhosts authentication refused for %.100s: "
00221 "no home directory %.200s", pw->pw_name, pw->pw_dir);
00222 auth_debug_add("Rhosts authentication refused for %.100s: "
00223 "no home directory %.200s", pw->pw_name, pw->pw_dir);
00224 return 0;
00225 }
00226 if (options.strict_modes &&
00227 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
00228 (st.st_mode & 022) != 0)) {
00229 logit("Rhosts authentication refused for %.100s: "
00230 "bad ownership or modes for home directory.", pw->pw_name);
00231 auth_debug_add("Rhosts authentication refused for %.100s: "
00232 "bad ownership or modes for home directory.", pw->pw_name);
00233 return 0;
00234 }
00235
00236 temporarily_use_uid(pw);
00237
00238
00239 for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
00240 rhosts_file_index++) {
00241
00242 snprintf(buf, sizeof buf, "%.500s/%.100s",
00243 pw->pw_dir, rhosts_files[rhosts_file_index]);
00244 if (stat(buf, &st) < 0)
00245 continue;
00246
00247
00248
00249
00250
00251
00252
00253 if (options.strict_modes &&
00254 ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
00255 (st.st_mode & 022) != 0)) {
00256 logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
00257 pw->pw_name, buf);
00258 auth_debug_add("Bad file modes for %.200s", buf);
00259 continue;
00260 }
00261
00262 if (options.ignore_rhosts) {
00263 auth_debug_add("Server has been configured to ignore %.100s.",
00264 rhosts_files[rhosts_file_index]);
00265 continue;
00266 }
00267
00268 if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name)) {
00269 auth_debug_add("Accepted by %.100s.",
00270 rhosts_files[rhosts_file_index]);
00271
00272 restore_uid();
00273 auth_debug_add("Accepted host %s ip %s client_user %s server_user %s",
00274 hostname, ipaddr, client_user, pw->pw_name);
00275 return 1;
00276 }
00277 }
00278
00279
00280 restore_uid();
00281 return 0;
00282 }
00283
00284 int
00285 auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
00286 const char *ipaddr)
00287 {
00288 int ret;
00289
00290 auth_debug_reset();
00291 ret = auth_rhosts2_raw(pw, client_user, hostname, ipaddr);
00292 if (!use_privsep)
00293 auth_debug_send();
00294 return ret;
00295 }