summaryrefslogtreecommitdiffstats
path: root/usr.bin/ssh/auth.c
diff options
context:
space:
mode:
authormarkus <markus@openbsd.org>2000-04-26 21:28:31 +0000
committermarkus <markus@openbsd.org>2000-04-26 21:28:31 +0000
commitcd03f1d40a9ce878ef76915b6f6130efceb10bd8 (patch)
treebacd93b27b821756ae265f592251b9277b3bd9fb /usr.bin/ssh/auth.c
parentrcsids where missing (diff)
downloadwireguard-openbsd-cd03f1d40a9ce878ef76915b6f6130efceb10bd8.tar.xz
wireguard-openbsd-cd03f1d40a9ce878ef76915b6f6130efceb10bd8.zip
split auth/sshconnect in one file per protocol version
Diffstat (limited to 'usr.bin/ssh/auth.c')
-rw-r--r--usr.bin/ssh/auth.c828
1 files changed, 2 insertions, 826 deletions
diff --git a/usr.bin/ssh/auth.c b/usr.bin/ssh/auth.c
index 7c88017e8d0..d3425a237a7 100644
--- a/usr.bin/ssh/auth.c
+++ b/usr.bin/ssh/auth.c
@@ -5,11 +5,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.5 2000/04/26 20:56:29 markus Exp $");
-
-#include <openssl/dsa.h>
-#include <openssl/rsa.h>
-#include <openssl/evp.h>
+RCSID("$OpenBSD: auth.c,v 1.6 2000/04/26 21:28:31 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
@@ -23,17 +19,13 @@ RCSID("$OpenBSD: auth.c,v 1.5 2000/04/26 20:56:29 markus Exp $");
#include "compat.h"
#include "channels.h"
#include "match.h"
+
#include "bufaux.h"
#include "ssh2.h"
#include "auth.h"
#include "session.h"
#include "dispatch.h"
-#include "key.h"
-#include "kex.h"
-#include "dsa.h"
-#include "uidswap.h"
-#include "channels.h"
/* import */
extern ServerOptions options;
@@ -117,819 +109,3 @@ allowed_user(struct passwd * pw)
/* We found no reason not to let this user try to log on... */
return 1;
}
-
-/* import */
-extern ServerOptions options;
-extern char *forced_command;
-
-/*
- * convert ssh auth msg type into description
- */
-char *
-get_authname(int type)
-{
- static char buf[1024];
- switch (type) {
- case SSH_CMSG_AUTH_PASSWORD:
- return "password";
- case SSH_CMSG_AUTH_RSA:
- return "rsa";
- case SSH_CMSG_AUTH_RHOSTS_RSA:
- return "rhosts-rsa";
- case SSH_CMSG_AUTH_RHOSTS:
- return "rhosts";
-#ifdef KRB4
- case SSH_CMSG_AUTH_KERBEROS:
- return "kerberos";
-#endif
-#ifdef SKEY
- case SSH_CMSG_AUTH_TIS_RESPONSE:
- return "s/key";
-#endif
- }
- snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
- return buf;
-}
-
-#define AUTH_FAIL_MAX 6
-#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
-#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
-
-/*
- * The user does not exist or access is denied,
- * but fake indication that authentication is needed.
- */
-void
-do_fake_authloop1(char *user)
-{
- int attempt = 0;
-
- log("Faking authloop for illegal user %.200s from %.200s port %d",
- user,
- get_remote_ipaddr(),
- get_remote_port());
-
- /* Indicate that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- /*
- * Keep reading packets, and always respond with a failure. This is
- * to avoid disclosing whether such a user really exists.
- */
- for (attempt = 1;; attempt++) {
- /* Read a packet. This will not return if the client disconnects. */
- int plen;
- int type = packet_read(&plen);
-#ifdef SKEY
- unsigned int dlen;
- char *password, *skeyinfo;
- password = NULL;
- /* Try to send a fake s/key challenge. */
- if (options.skey_authentication == 1 &&
- (skeyinfo = skey_fake_keyinfo(user)) != NULL) {
- if (type == SSH_CMSG_AUTH_TIS) {
- packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_string(skeyinfo, strlen(skeyinfo));
- packet_send();
- packet_write_wait();
- continue;
- } else if (type == SSH_CMSG_AUTH_PASSWORD &&
- options.password_authentication &&
- (password = packet_get_string(&dlen)) != NULL &&
- dlen == 5 &&
- strncasecmp(password, "s/key", 5) == 0 ) {
- packet_send_debug(skeyinfo);
- }
- }
- if (password != NULL)
- xfree(password);
-#endif
- if (attempt > AUTH_FAIL_MAX)
- packet_disconnect(AUTH_FAIL_MSG, user);
-
- /*
- * Send failure. This should be indistinguishable from a
- * failed authentication.
- */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
- /* NOTREACHED */
- abort();
-}
-
-/*
- * read packets and try to authenticate local user *pw.
- * return if authentication is successfull
- */
-void
-do_authloop(struct passwd * pw)
-{
- int attempt = 0;
- unsigned int bits;
- RSA *client_host_key;
- BIGNUM *n;
- char *client_user, *password;
- char user[1024];
- unsigned int dlen;
- int plen, nlen, elen;
- unsigned int ulen;
- int type = 0;
- void (*authlog) (const char *fmt,...) = verbose;
-
- /* Indicate that authentication is needed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
-
- for (attempt = 1;; attempt++) {
- int authenticated = 0;
- strlcpy(user, "", sizeof user);
-
- /* Get a packet from the client. */
- type = packet_read(&plen);
-
- /* Process the packet. */
- switch (type) {
-#ifdef AFS
- case SSH_CMSG_HAVE_KERBEROS_TGT:
- if (!options.kerberos_tgt_passing) {
- /* packet_get_all(); */
- verbose("Kerberos tgt passing disabled.");
- break;
- } else {
- /* Accept Kerberos tgt. */
- char *tgt = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
- if (!auth_kerberos_tgt(pw, tgt))
- verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
- xfree(tgt);
- }
- continue;
-
- case SSH_CMSG_HAVE_AFS_TOKEN:
- if (!options.afs_token_passing || !k_hasafs()) {
- /* packet_get_all(); */
- verbose("AFS token passing disabled.");
- break;
- } else {
- /* Accept AFS token. */
- char *token_string = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
- if (!auth_afs_token(pw, token_string))
- verbose("AFS token REFUSED for %s", pw->pw_name);
- xfree(token_string);
- }
- continue;
-#endif /* AFS */
-#ifdef KRB4
- case SSH_CMSG_AUTH_KERBEROS:
- if (!options.kerberos_authentication) {
- /* packet_get_all(); */
- verbose("Kerberos authentication disabled.");
- break;
- } else {
- /* Try Kerberos v4 authentication. */
- KTEXT_ST auth;
- char *tkt_user = NULL;
- char *kdata = packet_get_string((unsigned int *) &auth.length);
- packet_integrity_check(plen, 4 + auth.length, type);
-
- if (auth.length < MAX_KTXT_LEN)
- memcpy(auth.dat, kdata, auth.length);
- xfree(kdata);
-
- authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
-
- if (authenticated) {
- snprintf(user, sizeof user, " tktuser %s", tkt_user);
- xfree(tkt_user);
- }
- }
- break;
-#endif /* KRB4 */
-
- case SSH_CMSG_AUTH_RHOSTS:
- if (!options.rhosts_authentication) {
- verbose("Rhosts authentication disabled.");
- break;
- }
- /*
- * Get client user name. Note that we just have to
- * trust the client; this is one reason why rhosts
- * authentication is insecure. (Another is
- * IP-spoofing on a local network.)
- */
- client_user = packet_get_string(&ulen);
- packet_integrity_check(plen, 4 + ulen, type);
-
- /* Try to authenticate using /etc/hosts.equiv and
- .rhosts. */
- authenticated = auth_rhosts(pw, client_user);
-
- snprintf(user, sizeof user, " ruser %s", client_user);
- xfree(client_user);
- break;
-
- case SSH_CMSG_AUTH_RHOSTS_RSA:
- if (!options.rhosts_rsa_authentication) {
- verbose("Rhosts with RSA authentication disabled.");
- break;
- }
- /*
- * Get client user name. Note that we just have to
- * trust the client; root on the client machine can
- * claim to be any user.
- */
- client_user = packet_get_string(&ulen);
-
- /* Get the client host key. */
- client_host_key = RSA_new();
- if (client_host_key == NULL)
- fatal("RSA_new failed");
- client_host_key->e = BN_new();
- client_host_key->n = BN_new();
- if (client_host_key->e == NULL || client_host_key->n == NULL)
- fatal("BN_new failed");
- bits = packet_get_int();
- packet_get_bignum(client_host_key->e, &elen);
- packet_get_bignum(client_host_key->n, &nlen);
-
- if (bits != BN_num_bits(client_host_key->n))
- error("Warning: keysize mismatch for client_host_key: "
- "actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
- packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
-
- authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
- RSA_free(client_host_key);
-
- snprintf(user, sizeof user, " ruser %s", client_user);
- xfree(client_user);
- break;
-
- case SSH_CMSG_AUTH_RSA:
- if (!options.rsa_authentication) {
- verbose("RSA authentication disabled.");
- break;
- }
- /* RSA authentication requested. */
- n = BN_new();
- packet_get_bignum(n, &nlen);
- packet_integrity_check(plen, nlen, type);
- authenticated = auth_rsa(pw, n);
- BN_clear_free(n);
- break;
-
- case SSH_CMSG_AUTH_PASSWORD:
- if (!options.password_authentication) {
- verbose("Password authentication disabled.");
- break;
- }
- /*
- * Read user password. It is in plain text, but was
- * transmitted over the encrypted channel so it is
- * not visible to an outside observer.
- */
- password = packet_get_string(&dlen);
- packet_integrity_check(plen, 4 + dlen, type);
-
- /* Try authentication with the password. */
- authenticated = auth_password(pw, password);
-
- memset(password, 0, strlen(password));
- xfree(password);
- break;
-
-#ifdef SKEY
- case SSH_CMSG_AUTH_TIS:
- debug("rcvd SSH_CMSG_AUTH_TIS");
- if (options.skey_authentication == 1) {
- char *skeyinfo = skey_keyinfo(pw->pw_name);
- if (skeyinfo == NULL) {
- debug("generating fake skeyinfo for %.100s.", pw->pw_name);
- skeyinfo = skey_fake_keyinfo(pw->pw_name);
- }
- if (skeyinfo != NULL) {
- /* we send our s/key- in tis-challenge messages */
- debug("sending challenge '%s'", skeyinfo);
- packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
- packet_put_string(skeyinfo, strlen(skeyinfo));
- packet_send();
- packet_write_wait();
- continue;
- }
- }
- break;
- case SSH_CMSG_AUTH_TIS_RESPONSE:
- debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
- if (options.skey_authentication == 1) {
- char *response = packet_get_string(&dlen);
- debug("skey response == '%s'", response);
- packet_integrity_check(plen, 4 + dlen, type);
- authenticated = (skey_haskey(pw->pw_name) == 0 &&
- skey_passcheck(pw->pw_name, response) != -1);
- xfree(response);
- }
- break;
-#else
- case SSH_CMSG_AUTH_TIS:
- /* TIS Authentication is unsupported */
- log("TIS authentication unsupported.");
- break;
-#endif
-
- default:
- /*
- * Any unknown messages will be ignored (and failure
- * returned) during authentication.
- */
- log("Unknown message during authentication: type %d", type);
- break;
- }
-
- /*
- * Check if the user is logging in as root and root logins
- * are disallowed.
- * Note that root login is allowed for forced commands.
- */
- if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
- if (forced_command) {
- log("Root login accepted for forced command.");
- } else {
- authenticated = 0;
- log("ROOT LOGIN REFUSED FROM %.200s",
- get_canonical_hostname());
- }
- }
-
- /* Raise logging level */
- if (authenticated ||
- attempt == AUTH_FAIL_LOG ||
- type == SSH_CMSG_AUTH_PASSWORD)
- authlog = log;
-
- authlog("%s %s for %.200s from %.200s port %d%s",
- authenticated ? "Accepted" : "Failed",
- get_authname(type),
- pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
- get_remote_ipaddr(),
- get_remote_port(),
- user);
-
- if (authenticated)
- return;
-
- if (attempt > AUTH_FAIL_MAX)
- packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
-
- /* Send a message indicating that the authentication attempt failed. */
- packet_start(SSH_SMSG_FAILURE);
- packet_send();
- packet_write_wait();
- }
-}
-
-/*
- * Performs authentication of an incoming connection. Session key has already
- * been exchanged and encryption is enabled.
- */
-void
-do_authentication()
-{
- struct passwd *pw, pwcopy;
- int plen;
- unsigned int ulen;
- char *user;
-
- /* Get the name of the user that we wish to log in as. */
- packet_read_expect(&plen, SSH_CMSG_USER);
-
- /* Get the user name. */
- user = packet_get_string(&ulen);
- packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
-
- setproctitle("%s", user);
-
-#ifdef AFS
- /* If machine has AFS, set process authentication group. */
- if (k_hasafs()) {
- k_setpag();
- k_unlog();
- }
-#endif /* AFS */
-
- /* Verify that the user is a valid user. */
- pw = getpwnam(user);
- if (!pw || !allowed_user(pw))
- do_fake_authloop1(user);
- xfree(user);
-
- /* Take a copy of the returned structure. */
- memset(&pwcopy, 0, sizeof(pwcopy));
- pwcopy.pw_name = xstrdup(pw->pw_name);
- pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
- pwcopy.pw_uid = pw->pw_uid;
- pwcopy.pw_gid = pw->pw_gid;
- pwcopy.pw_dir = xstrdup(pw->pw_dir);
- pwcopy.pw_shell = xstrdup(pw->pw_shell);
- pw = &pwcopy;
-
- /*
- * If we are not running as root, the user must have the same uid as
- * the server.
- */
- if (getuid() != 0 && pw->pw_uid != getuid())
- packet_disconnect("Cannot change user when server not running as root.");
-
- debug("Attempting authentication for %.100s.", pw->pw_name);
-
- /* If the user has no password, accept authentication immediately. */
- if (options.password_authentication &&
-#ifdef KRB4
- (!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
-#endif /* KRB4 */
- auth_password(pw, "")) {
- /* Authentication with empty password succeeded. */
- log("Login for user %s from %.100s, accepted without authentication.",
- pw->pw_name, get_remote_ipaddr());
- } else {
- /* Loop until the user has been authenticated or the
- connection is closed, do_authloop() returns only if
- authentication is successfull */
- do_authloop(pw);
- }
-
- /* The user has been authenticated and accepted. */
- packet_start(SSH_SMSG_SUCCESS);
- packet_send();
- packet_write_wait();
-
- /* Perform session preparation. */
- do_authenticated(pw);
-}
-
-/* import */
-extern ServerOptions options;
-extern unsigned char *session_id2;
-extern int session_id2_len;
-
-/* protocol */
-
-void input_service_request(int type, int plen);
-void input_userauth_request(int type, int plen);
-void protocol_error(int type, int plen);
-
-/* auth */
-int ssh2_auth_none(struct passwd *pw);
-int ssh2_auth_password(struct passwd *pw);
-int ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen);
-
-/* helper */
-struct passwd* auth_set_user(char *u, char *s);
-int user_dsa_key_allowed(struct passwd *pw, Key *key);
-
-typedef struct Authctxt Authctxt;
-struct Authctxt {
- char *user;
- char *service;
- struct passwd pw;
- int valid;
-};
-static Authctxt *authctxt = NULL;
-static int userauth_success = 0;
-
-/* set and get current user */
-
-struct passwd*
-auth_get_user(void)
-{
- return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL;
-}
-
-struct passwd*
-auth_set_user(char *u, char *s)
-{
- struct passwd *pw, *copy;
-
- if (authctxt == NULL) {
- authctxt = xmalloc(sizeof(*authctxt));
- authctxt->valid = 0;
- authctxt->user = xstrdup(u);
- authctxt->service = xstrdup(s);
- setproctitle("%s", u);
- pw = getpwnam(u);
- if (!pw || !allowed_user(pw)) {
- log("auth_set_user: bad user %s", u);
- return NULL;
- }
- copy = &authctxt->pw;
- memset(copy, 0, sizeof(*copy));
- copy->pw_name = xstrdup(pw->pw_name);
- copy->pw_passwd = xstrdup(pw->pw_passwd);
- copy->pw_uid = pw->pw_uid;
- copy->pw_gid = pw->pw_gid;
- copy->pw_dir = xstrdup(pw->pw_dir);
- copy->pw_shell = xstrdup(pw->pw_shell);
- authctxt->valid = 1;
- } else {
- if (strcmp(u, authctxt->user) != 0 ||
- strcmp(s, authctxt->service) != 0) {
- log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
- u, s, authctxt->user, authctxt->service);
- return NULL;
- }
- }
- return auth_get_user();
-}
-
-/*
- * loop until userauth_success == TRUE
- */
-
-void
-do_authentication2()
-{
- dispatch_init(&protocol_error);
- dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
- dispatch_run(DISPATCH_BLOCK, &userauth_success);
- do_authenticated2();
-}
-
-void
-protocol_error(int type, int plen)
-{
- log("auth: protocol error: type %d plen %d", type, plen);
- packet_start(SSH2_MSG_UNIMPLEMENTED);
- packet_put_int(0);
- packet_send();
- packet_write_wait();
-}
-
-void
-input_service_request(int type, int plen)
-{
- unsigned int len;
- int accept = 0;
- char *service = packet_get_string(&len);
- packet_done();
-
- if (strcmp(service, "ssh-userauth") == 0) {
- if (!userauth_success) {
- accept = 1;
- /* now we can handle user-auth requests */
- dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
- }
- }
- /* XXX all other service requests are denied */
-
- if (accept) {
- packet_start(SSH2_MSG_SERVICE_ACCEPT);
- packet_put_cstring(service);
- packet_send();
- packet_write_wait();
- } else {
- debug("bad service request %s", service);
- packet_disconnect("bad service request %s", service);
- }
- xfree(service);
-}
-
-void
-input_userauth_request(int type, int plen)
-{
- static int try = 0;
- unsigned int len, rlen;
- int authenticated = 0;
- char *raw, *user, *service, *method;
- struct passwd *pw;
-
- if (++try == AUTH_FAIL_MAX)
- packet_disconnect("too many failed userauth_requests");
-
- raw = packet_get_raw(&rlen);
- if (plen != rlen)
- fatal("plen != rlen");
- user = packet_get_string(&len);
- service = packet_get_string(&len);
- method = packet_get_string(&len);
- debug("userauth-request for user %s service %s method %s", user, service, method);
-
- /* XXX we only allow the ssh-connection service */
- pw = auth_set_user(user, service);
- if (pw && strcmp(service, "ssh-connection")==0) {
- if (strcmp(method, "none") == 0) {
- authenticated = ssh2_auth_none(pw);
- } else if (strcmp(method, "password") == 0) {
- authenticated = ssh2_auth_password(pw);
- } else if (strcmp(method, "publickey") == 0) {
- authenticated = ssh2_auth_pubkey(pw, raw, rlen);
- }
- }
- /* XXX check if other auth methods are needed */
- if (authenticated == 1) {
- log("userauth success for %s method %s", user, method);
- /* turn off userauth */
- dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &protocol_error);
- packet_start(SSH2_MSG_USERAUTH_SUCCESS);
- packet_send();
- packet_write_wait();
- /* now we can break out */
- userauth_success = 1;
- } else if (authenticated == 0) {
- log("userauth failure for %s method %s", user, method);
- packet_start(SSH2_MSG_USERAUTH_FAILURE);
- packet_put_cstring("publickey,password"); /* XXX dynamic */
- packet_put_char(0); /* XXX partial success, unused */
- packet_send();
- packet_write_wait();
- } else {
- log("userauth postponed for %s method %s", user, method);
- }
- xfree(service);
- xfree(user);
- xfree(method);
-}
-
-int
-ssh2_auth_none(struct passwd *pw)
-{
- packet_done();
- return auth_password(pw, "");
-}
-int
-ssh2_auth_password(struct passwd *pw)
-{
- char *password;
- int authenticated = 0;
- int change;
- unsigned int len;
- change = packet_get_char();
- if (change)
- log("password change not supported");
- password = packet_get_string(&len);
- packet_done();
- if (auth_password(pw, password))
- authenticated = 1;
- memset(password, 0, len);
- xfree(password);
- return authenticated;
-}
-
-int
-ssh2_auth_pubkey(struct passwd *pw, unsigned char *raw, unsigned int rlen)
-{
- Buffer b;
- Key *key;
- char *pkalg, *pkblob, *sig;
- unsigned int alen, blen, slen;
- int have_sig;
- int authenticated = 0;
-
- have_sig = packet_get_char();
- pkalg = packet_get_string(&alen);
- if (strcmp(pkalg, KEX_DSS) != 0) {
- xfree(pkalg);
- log("bad pkalg %s", pkalg); /*XXX*/
- return 0;
- }
- pkblob = packet_get_string(&blen);
- key = dsa_key_from_blob(pkblob, blen);
-
- if (have_sig && key != NULL) {
- sig = packet_get_string(&slen);
- packet_done();
- buffer_init(&b);
- buffer_append(&b, session_id2, session_id2_len);
- buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
- if (slen + 4 > rlen)
- fatal("bad rlen/slen");
- buffer_append(&b, raw, rlen - slen - 4);
-#ifdef DEBUG_DSS
- buffer_dump(&b);
-#endif
- /* test for correct signature */
- if (user_dsa_key_allowed(pw, key) &&
- dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
- authenticated = 1;
- buffer_clear(&b);
- xfree(sig);
- } else if (!have_sig && key != NULL) {
- packet_done();
- debug("test key...");
- /* test whether pkalg/pkblob are acceptable */
- /* XXX fake reply and always send PK_OK ? */
- if (user_dsa_key_allowed(pw, key)) {
- packet_start(SSH2_MSG_USERAUTH_PK_OK);
- packet_put_string(pkalg, alen);
- packet_put_string(pkblob, blen);
- packet_send();
- packet_write_wait();
- authenticated = -1;
- }
- }
- xfree(pkalg);
- xfree(pkblob);
- return authenticated;
-}
-
-/* return 1 if user allows given key */
-int
-user_dsa_key_allowed(struct passwd *pw, Key *key)
-{
- char line[8192], file[1024];
- int found_key = 0;
- unsigned int bits = -1;
- FILE *f;
- unsigned long linenum = 0;
- struct stat st;
- Key *found;
-
- /* Temporarily use the user's uid. */
- temporarily_use_uid(pw->pw_uid);
-
- /* The authorized keys. */
- snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
- SSH_USER_PERMITTED_KEYS2);
-
- /* Fail quietly if file does not exist */
- if (stat(file, &st) < 0) {
- /* Restore the privileged uid. */
- restore_uid();
- return 0;
- }
- /* Open the file containing the authorized keys. */
- f = fopen(file, "r");
- if (!f) {
- /* Restore the privileged uid. */
- restore_uid();
- packet_send_debug("Could not open %.900s for reading.", file);
- packet_send_debug("If your home is on an NFS volume, it may need to be world-readable.");
- return 0;
- }
- if (options.strict_modes) {
- int fail = 0;
- char buf[1024];
- /* Check open file in order to avoid open/stat races */
- if (fstat(fileno(f), &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf, "DSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.", pw->pw_name, file);
- fail = 1;
- } else {
- /* Check path to SSH_USER_PERMITTED_KEYS */
- int i;
- static const char *check[] = {
- "", SSH_USER_DIR, NULL
- };
- for (i = 0; check[i]; i++) {
- snprintf(line, sizeof line, "%.500s/%.100s",
- pw->pw_dir, check[i]);
- if (stat(line, &st) < 0 ||
- (st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
- (st.st_mode & 022) != 0) {
- snprintf(buf, sizeof buf,
- "DSA authentication refused for %.100s: "
- "bad ownership or modes for '%s'.",
- pw->pw_name, line);
- fail = 1;
- break;
- }
- }
- }
- if (fail) {
- log(buf);
- fclose(f);
- restore_uid();
- return 0;
- }
- }
- found_key = 0;
- found = key_new(KEY_DSA);
-
- while (fgets(line, sizeof(line), f)) {
- char *cp;
- linenum++;
- /* Skip leading whitespace, empty and comment lines. */
- for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
- ;
- if (!*cp || *cp == '\n' || *cp == '#')
- continue;
- bits = key_read(found, &cp);
- if (bits == 0)
- continue;
- if (key_equal(found, key)) {
- found_key = 1;
- debug("matching key found: file %s, line %ld",
- file, linenum);
- break;
- }
- }
- restore_uid();
- fclose(f);
- key_free(found);
- return found_key;
-}