2 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * As far as I am concerned, the code I have written for this software
6 * can be used freely for any purpose. Any derived versions of this
7 * software must be clearly marked as such, and if the derived work is
8 * incompatible with the protocol description in the RFC file, it must be
9 * called by a name other than "ssh" or "Secure Shell".
13 RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
32 extern ServerOptions options;
33 extern char *forced_command;
35 #ifdef WITH_AIXAUTHENTICATE
36 extern char *aixloginmsg;
37 #endif /* WITH_AIXAUTHENTICATE */
39 extern int saved_argc;
40 extern char **saved_argv;
41 #endif /* HAVE_OSF_SIA */
44 * convert ssh auth msg type into description
47 get_authname(int type)
49 static char buf[1024];
51 case SSH_CMSG_AUTH_PASSWORD:
53 case SSH_CMSG_AUTH_RSA:
55 case SSH_CMSG_AUTH_RHOSTS_RSA:
57 case SSH_CMSG_AUTH_RHOSTS:
60 case SSH_CMSG_AUTH_KERBEROS:
64 case SSH_CMSG_AUTH_TIS_RESPONSE:
68 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
73 * read packets and try to authenticate local user 'luser'.
74 * return if authentication is successfull. not that pw == NULL
75 * if the user does not exists or is not allowed to login.
76 * each auth method has to 'fake' authentication for nonexisting
80 do_authloop(struct passwd * pw, char *luser)
82 int authenticated = 0;
87 char *client_user, *password;
93 void (*authlog) (const char *fmt,...) = verbose;
95 /* Indicate that authentication is needed. */
96 packet_start(SSH_SMSG_FAILURE);
102 for (attempt = 1;; attempt++) {
103 /* default to fail */
106 strlcpy(user, "", sizeof user);
108 /* Get a packet from the client. */
109 type = packet_read(&plen);
111 /* Process the packet. */
114 case SSH_CMSG_HAVE_KERBEROS_TGT:
115 if (!options.kerberos_tgt_passing) {
116 verbose("Kerberos tgt passing disabled.");
119 /* Accept Kerberos tgt. */
120 char *tgt = packet_get_string(&dlen);
121 packet_integrity_check(plen, 4 + dlen, type);
122 if (!auth_kerberos_tgt(pw, tgt))
123 verbose("Kerberos tgt REFUSED for %.100s", luser);
128 case SSH_CMSG_HAVE_AFS_TOKEN:
129 if (!options.afs_token_passing || !k_hasafs()) {
130 verbose("AFS token passing disabled.");
133 /* Accept AFS token. */
134 char *token_string = packet_get_string(&dlen);
135 packet_integrity_check(plen, 4 + dlen, type);
136 if (!auth_afs_token(pw, token_string))
137 verbose("AFS token REFUSED for %.100s", luser);
143 case SSH_CMSG_AUTH_KERBEROS:
144 if (!options.kerberos_authentication) {
145 /* packet_get_all(); */
146 verbose("Kerberos authentication disabled.");
149 /* Try Kerberos v4 authentication. */
151 char *tkt_user = NULL;
152 char *kdata = packet_get_string((unsigned int *) &auth.length);
153 packet_integrity_check(plen, 4 + auth.length, type);
155 if (auth.length < MAX_KTXT_LEN)
156 memcpy(auth.dat, kdata, auth.length);
160 authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
162 snprintf(user, sizeof user, " tktuser %s", tkt_user);
170 case SSH_CMSG_AUTH_RHOSTS:
171 if (!options.rhosts_authentication) {
172 verbose("Rhosts authentication disabled.");
176 * Get client user name. Note that we just have to
177 * trust the client; this is one reason why rhosts
178 * authentication is insecure. (Another is
179 * IP-spoofing on a local network.)
181 client_user = packet_get_string(&ulen);
182 packet_integrity_check(plen, 4 + ulen, type);
184 /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
185 authenticated = auth_rhosts(pw, client_user);
187 snprintf(user, sizeof user, " ruser %s", client_user);
190 case SSH_CMSG_AUTH_RHOSTS_RSA:
191 if (!options.rhosts_rsa_authentication) {
192 verbose("Rhosts with RSA authentication disabled.");
196 * Get client user name. Note that we just have to
197 * trust the client; root on the client machine can
198 * claim to be any user.
200 client_user = packet_get_string(&ulen);
202 /* Get the client host key. */
203 client_host_key = RSA_new();
204 if (client_host_key == NULL)
205 fatal("RSA_new failed");
206 client_host_key->e = BN_new();
207 client_host_key->n = BN_new();
208 if (client_host_key->e == NULL || client_host_key->n == NULL)
209 fatal("BN_new failed");
210 bits = packet_get_int();
211 packet_get_bignum(client_host_key->e, &elen);
212 packet_get_bignum(client_host_key->n, &nlen);
214 if (bits != BN_num_bits(client_host_key->n))
215 verbose("Warning: keysize mismatch for client_host_key: "
216 "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
217 packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
219 authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
220 RSA_free(client_host_key);
222 snprintf(user, sizeof user, " ruser %s", client_user);
225 case SSH_CMSG_AUTH_RSA:
226 if (!options.rsa_authentication) {
227 verbose("RSA authentication disabled.");
230 /* RSA authentication requested. */
232 packet_get_bignum(n, &nlen);
233 packet_integrity_check(plen, nlen, type);
234 authenticated = auth_rsa(pw, n);
238 case SSH_CMSG_AUTH_PASSWORD:
239 if (!options.password_authentication) {
240 verbose("Password authentication disabled.");
244 * Read user password. It is in plain text, but was
245 * transmitted over the encrypted channel so it is
246 * not visible to an outside observer.
248 password = packet_get_string(&dlen);
249 packet_integrity_check(plen, 4 + dlen, type);
252 /* Do PAM auth with password */
253 authenticated = auth_pam_password(pw, password);
254 #elif defined(HAVE_OSF_SIA)
255 /* Do SIA auth with password */
256 if (sia_validate_user(NULL, saved_argc, saved_argv,
257 get_canonical_hostname(), pw->pw_name, NULL, 0,
258 NULL, password) == SIASUCCESS) {
261 #else /* !USE_PAM && !HAVE_OSF_SIA */
262 /* Try authentication with the password. */
263 authenticated = auth_password(pw, password);
266 memset(password, 0, strlen(password));
271 case SSH_CMSG_AUTH_TIS:
272 debug("rcvd SSH_CMSG_AUTH_TIS");
273 if (options.skey_authentication == 1) {
274 char *skeyinfo = NULL;
276 skey_keyinfo(pw->pw_name);
277 if (skeyinfo == NULL) {
278 debug("generating fake skeyinfo for %.100s.", luser);
279 skeyinfo = skey_fake_keyinfo(luser);
281 if (skeyinfo != NULL) {
282 /* we send our s/key- in tis-challenge messages */
283 debug("sending challenge '%s'", skeyinfo);
284 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
285 packet_put_cstring(skeyinfo);
292 case SSH_CMSG_AUTH_TIS_RESPONSE:
293 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
294 if (options.skey_authentication == 1) {
295 char *response = packet_get_string(&dlen);
296 debug("skey response == '%s'", response);
297 packet_integrity_check(plen, 4 + dlen, type);
298 authenticated = (pw != NULL &&
299 skey_haskey(pw->pw_name) == 0 &&
300 skey_passcheck(pw->pw_name, response) != -1);
305 case SSH_CMSG_AUTH_TIS:
306 /* TIS Authentication is unsupported */
307 log("TIS authentication unsupported.");
313 * Any unknown messages will be ignored (and failure
314 * returned) during authentication.
316 log("Unknown message during authentication: type %d", type);
319 if (authenticated && pw == NULL)
320 fatal("internal error: authenticated for pw == NULL");
324 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,pw->pw_uid)) {
325 packet_disconnect("Authentication rejected for uid %d.",
332 * Check if the user is logging in as root and root logins
334 * Note that root login is allowed for forced commands.
336 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
337 if (forced_command) {
338 log("Root login accepted for forced command.");
341 log("ROOT LOGIN REFUSED FROM %.200s",
342 get_canonical_hostname());
346 /* Raise logging level */
348 attempt == AUTH_FAIL_LOG ||
349 type == SSH_CMSG_AUTH_PASSWORD)
352 authlog("%s %s for %s%.100s from %.200s port %d%s",
353 authenticated ? "Accepted" : "Failed",
355 pw ? "" : "illegal user ",
356 pw && pw->pw_uid == 0 ? "ROOT" : luser,
362 if (authenticated && !do_pam_account(pw->pw_name, client_user))
366 if (client_user != NULL) {
374 if (attempt > AUTH_FAIL_MAX) {
375 #ifdef WITH_AIXAUTHENTICATE
376 loginfailed(user,get_canonical_hostname(),"ssh");
377 #endif /* WITH_AIXAUTHENTICATE */
378 packet_disconnect(AUTH_FAIL_MSG, luser);
381 /* Send a message indicating that the authentication attempt failed. */
382 packet_start(SSH_SMSG_FAILURE);
389 * Performs authentication of an incoming connection. Session key has already
390 * been exchanged and encryption is enabled.
395 struct passwd *pw, pwcopy;
400 /* Get the name of the user that we wish to log in as. */
401 packet_read_expect(&plen, SSH_CMSG_USER);
403 /* Get the user name. */
404 user = packet_get_string(&ulen);
405 packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
407 setproctitle("%s", user);
410 /* If machine has AFS, set process authentication group. */
417 /* Verify that the user is a valid user. */
419 if (pw && allowed_user(pw)) {
420 /* Take a copy of the returned structure. */
421 memset(&pwcopy, 0, sizeof(pwcopy));
422 pwcopy.pw_name = xstrdup(pw->pw_name);
423 pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
424 pwcopy.pw_uid = pw->pw_uid;
425 pwcopy.pw_gid = pw->pw_gid;
426 #ifdef HAVE_PW_CLASS_IN_PASSWD
427 pwcopy.pw_class = xstrdup(pw->pw_class);
429 pwcopy.pw_dir = xstrdup(pw->pw_dir);
430 pwcopy.pw_shell = xstrdup(pw->pw_shell);
442 * If we are not running as root, the user must have the same uid as
443 * the server. (Unless you are running Windows)
446 if (getuid() != 0 && pw && pw->pw_uid != getuid())
447 packet_disconnect("Cannot change user when server not running as root.");
450 debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
452 /* If the user has no password, accept authentication immediately. */
453 if (options.password_authentication &&
455 (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
458 auth_pam_password(pw, "")) {
459 #elif defined(HAVE_OSF_SIA)
460 (sia_validate_user(NULL, saved_argc, saved_argv,
461 get_canonical_hostname(), pw->pw_name, NULL, 0,
462 NULL, "") == SIASUCCESS)) {
463 #else /* !HAVE_OSF_SIA && !USE_PAM */
464 auth_password(pw, "")) {
466 /* Authentication with empty password succeeded. */
467 log("Login for user %s from %.100s, accepted without authentication.",
468 user, get_remote_ipaddr());
470 /* Loop until the user has been authenticated or the
471 connection is closed, do_authloop() returns only if
472 authentication is successfull */
473 do_authloop(pw, user);
476 fatal("internal error, authentication successfull for user '%.100s'", user);
478 /* The user has been authenticated and accepted. */
479 packet_start(SSH_SMSG_SUCCESS);
483 #ifdef WITH_AIXAUTHENTICATE
484 /* We don't have a pty yet, so just label the line as "ssh" */
485 if (loginsuccess(user,get_canonical_hostname(),"ssh",&aixloginmsg) < 0)
487 #endif /* WITH_AIXAUTHENTICATE */
489 /* Perform session preparation. */
490 do_authenticated(pw);