⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sshconnect1.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * Code to connect to a remote host, and to perform the client side of the * login (authentication) dialog. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". */#include "includes.h"RCSID("$OpenBSD: sshconnect1.c,v 1.51 2002/05/23 19:24:30 markus Exp $");#include <openssl/bn.h>#include <openssl/md5.h>#ifdef KRB4#include <krb.h>#endif#ifdef KRB5#include <krb5.h>#ifndef HEIMDAL#define krb5_get_err_text(context,code) error_message(code)#endif /* !HEIMDAL */#endif#ifdef AFS#include <kafs.h>#include "radix.h"#endif#include "ssh.h"#include "ssh1.h"#include "xmalloc.h"#include "rsa.h"#include "buffer.h"#include "packet.h"#include "mpaux.h"#include "uidswap.h"#include "log.h"#include "readconf.h"#include "key.h"#include "authfd.h"#include "sshconnect.h"#include "authfile.h"#include "readpass.h"#include "cipher.h"#include "canohost.h"#include "auth.h"/* Session id for the current session. */u_char session_id[16];u_int supported_authentications = 0;extern Options options;extern char *__progname;/* * Checks if the user has an authentication agent, and if so, tries to * authenticate using the agent. */static inttry_agent_authentication(void){	int type;	char *comment;	AuthenticationConnection *auth;	u_char response[16];	u_int i;	Key *key;	BIGNUM *challenge;	/* Get connection to the agent. */	auth = ssh_get_authentication_connection();	if (!auth)		return 0;	if ((challenge = BN_new()) == NULL)		fatal("try_agent_authentication: BN_new failed");	/* Loop through identities served by the agent. */	for (key = ssh_get_first_identity(auth, &comment, 1);	    key != NULL;	    key = ssh_get_next_identity(auth, &comment, 1)) {		/* Try this identity. */		debug("Trying RSA authentication via agent with '%.100s'", comment);		xfree(comment);		/* Tell the server that we are willing to authenticate using this key. */		packet_start(SSH_CMSG_AUTH_RSA);		packet_put_bignum(key->rsa->n);		packet_send();		packet_write_wait();		/* Wait for server's response. */		type = packet_read();		/* The server sends failure if it doesn\'t like our key or		   does not support RSA authentication. */		if (type == SSH_SMSG_FAILURE) {			debug("Server refused our key.");			key_free(key);			continue;		}		/* Otherwise it should have sent a challenge. */		if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)			packet_disconnect("Protocol error during RSA authentication: %d",					  type);		packet_get_bignum(challenge);		packet_check_eom();		debug("Received RSA challenge from server.");		/* Ask the agent to decrypt the challenge. */		if (!ssh_decrypt_challenge(auth, key, challenge, session_id, 1, response)) {			/*			 * The agent failed to authenticate this identifier			 * although it advertised it supports this.  Just			 * return a wrong value.			 */			log("Authentication agent failed to decrypt challenge.");			memset(response, 0, sizeof(response));		}		key_free(key);		debug("Sending response to RSA challenge.");		/* Send the decrypted challenge back to the server. */		packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);		for (i = 0; i < 16; i++)			packet_put_char(response[i]);		packet_send();		packet_write_wait();		/* Wait for response from the server. */		type = packet_read();		/* The server returns success if it accepted the authentication. */		if (type == SSH_SMSG_SUCCESS) {			ssh_close_authentication_connection(auth);			BN_clear_free(challenge);			debug("RSA authentication accepted by server.");			return 1;		}		/* Otherwise it should return failure. */		if (type != SSH_SMSG_FAILURE)			packet_disconnect("Protocol error waiting RSA auth response: %d",					  type);	}	ssh_close_authentication_connection(auth);	BN_clear_free(challenge);	debug("RSA authentication using agent refused.");	return 0;}/* * Computes the proper response to a RSA challenge, and sends the response to * the server. */static voidrespond_to_rsa_challenge(BIGNUM * challenge, RSA * prv){	u_char buf[32], response[16];	MD5_CTX md;	int i, len;	/* Decrypt the challenge using the private key. */	/* XXX think about Bleichenbacher, too */	if (rsa_private_decrypt(challenge, challenge, prv) <= 0)		packet_disconnect(		    "respond_to_rsa_challenge: rsa_private_decrypt failed");	/* Compute the response. */	/* The response is MD5 of decrypted challenge plus session id. */	len = BN_num_bytes(challenge);	if (len <= 0 || len > sizeof(buf))		packet_disconnect(		    "respond_to_rsa_challenge: bad challenge length %d", len);	memset(buf, 0, sizeof(buf));	BN_bn2bin(challenge, buf + sizeof(buf) - len);	MD5_Init(&md);	MD5_Update(&md, buf, 32);	MD5_Update(&md, session_id, 16);	MD5_Final(response, &md);	debug("Sending response to host key RSA challenge.");	/* Send the response back to the server. */	packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);	for (i = 0; i < 16; i++)		packet_put_char(response[i]);	packet_send();	packet_write_wait();	memset(buf, 0, sizeof(buf));	memset(response, 0, sizeof(response));	memset(&md, 0, sizeof(md));}/* * Checks if the user has authentication file, and if so, tries to authenticate * the user using it. */static inttry_rsa_authentication(int idx){	BIGNUM *challenge;	Key *public, *private;	char buf[300], *passphrase, *comment, *authfile;	int i, type, quit;	public = options.identity_keys[idx];	authfile = options.identity_files[idx];	comment = xstrdup(authfile);	debug("Trying RSA authentication with key '%.100s'", comment);	/* Tell the server that we are willing to authenticate using this key. */	packet_start(SSH_CMSG_AUTH_RSA);	packet_put_bignum(public->rsa->n);	packet_send();	packet_write_wait();	/* Wait for server's response. */	type = packet_read();	/*	 * The server responds with failure if it doesn\'t like our key or	 * doesn\'t support RSA authentication.	 */	if (type == SSH_SMSG_FAILURE) {		debug("Server refused our key.");		xfree(comment);		return 0;	}	/* Otherwise, the server should respond with a challenge. */	if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)		packet_disconnect("Protocol error during RSA authentication: %d", type);	/* Get the challenge from the packet. */	if ((challenge = BN_new()) == NULL)		fatal("try_rsa_authentication: BN_new failed");	packet_get_bignum(challenge);	packet_check_eom();	debug("Received RSA challenge from server.");	/*	 * If the key is not stored in external hardware, we have to	 * load the private key.  Try first with empty passphrase; if it	 * fails, ask for a passphrase.	 */	if (public->flags && KEY_FLAG_EXT)		private = public;	else		private = key_load_private_type(KEY_RSA1, authfile, "", NULL);	if (private == NULL && !options.batch_mode) {		snprintf(buf, sizeof(buf),		    "Enter passphrase for RSA key '%.100s': ", comment);		for (i = 0; i < options.number_of_password_prompts; i++) {			passphrase = read_passphrase(buf, 0);			if (strcmp(passphrase, "") != 0) {				private = key_load_private_type(KEY_RSA1,				    authfile, passphrase, NULL);				quit = 0;			} else {				debug2("no passphrase given, try next key");				quit = 1;			}			memset(passphrase, 0, strlen(passphrase));			xfree(passphrase);			if (private != NULL || quit)				break;			debug2("bad passphrase given, try again...");		}	}	/* We no longer need the comment. */	xfree(comment);	if (private == NULL) {		if (!options.batch_mode)			error("Bad passphrase.");		/* Send a dummy response packet to avoid protocol error. */		packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);		for (i = 0; i < 16; i++)			packet_put_char(0);		packet_send();		packet_write_wait();		/* Expect the server to reject it... */		packet_read_expect(SSH_SMSG_FAILURE);		BN_clear_free(challenge);		return 0;	}	/* Compute and send a response to the challenge. */	respond_to_rsa_challenge(challenge, private->rsa);	/* Destroy the private key unless it in external hardware. */	if (!(private->flags & KEY_FLAG_EXT))		key_free(private);	/* We no longer need the challenge. */	BN_clear_free(challenge);	/* Wait for response from the server. */	type = packet_read();	if (type == SSH_SMSG_SUCCESS) {		debug("RSA authentication accepted by server.");		return 1;	}	if (type != SSH_SMSG_FAILURE)		packet_disconnect("Protocol error waiting RSA auth response: %d", type);	debug("RSA authentication refused.");	return 0;}/* * Tries to authenticate the user using combined rhosts or /etc/hosts.equiv * authentication and RSA host authentication. */static inttry_rhosts_rsa_authentication(const char *local_user, Key * host_key){	int type;	BIGNUM *challenge;	debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");	/* Tell the server that we are willing to authenticate using this key. */	packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);	packet_put_cstring(local_user);	packet_put_int(BN_num_bits(host_key->rsa->n));	packet_put_bignum(host_key->rsa->e);	packet_put_bignum(host_key->rsa->n);	packet_send();	packet_write_wait();	/* Wait for server's response. */	type = packet_read();	/* The server responds with failure if it doesn't admit our	   .rhosts authentication or doesn't know our host key. */	if (type == SSH_SMSG_FAILURE) {		debug("Server refused our rhosts authentication or host key.");		return 0;	}	/* Otherwise, the server should respond with a challenge. */	if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)		packet_disconnect("Protocol error during RSA authentication: %d", type);	/* Get the challenge from the packet. */	if ((challenge = BN_new()) == NULL)		fatal("try_rhosts_rsa_authentication: BN_new failed");	packet_get_bignum(challenge);	packet_check_eom();	debug("Received RSA challenge for host key from server.");	/* Compute a response to the challenge. */	respond_to_rsa_challenge(challenge, host_key->rsa);	/* We no longer need the challenge. */	BN_clear_free(challenge);	/* Wait for response from the server. */	type = packet_read();	if (type == SSH_SMSG_SUCCESS) {		debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");		return 1;	}	if (type != SSH_SMSG_FAILURE)		packet_disconnect("Protocol error waiting RSA auth response: %d", type);	debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");	return 0;}#ifdef KRB4static inttry_krb4_authentication(void){	KTEXT_ST auth;		/* Kerberos data */	char *reply;	char inst[INST_SZ];	char *realm;	CREDENTIALS cred;	int r, type;	socklen_t slen;	Key_schedule schedule;	u_long checksum, cksum;	MSG_DAT msg_data;	struct sockaddr_in local, foreign;	struct stat st;	/* Don't do anything if we don't have any tickets. */	if (stat(tkt_string(), &st) < 0)		return 0;	strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)),	    INST_SZ);	realm = (char *)krb_realmofhost(get_canonical_hostname(1));	if (!realm) {		debug("Kerberos v4: no realm for %s", get_canonical_hostname(1));		return 0;	}	/* This can really be anything. */	checksum = (u_long)getpid();	r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);	if (r != KSUCCESS) {		debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]);		return 0;	}	/* Get session key to decrypt the server's reply with. */	r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);	if (r != KSUCCESS) {		debug("get_cred failed: %s", krb_err_txt[r]);		return 0;	}	des_key_sched((des_cblock *) cred.session, schedule);	/* Send authentication info to server. */	packet_start(SSH_CMSG_AUTH_KERBEROS);	packet_put_string((char *) auth.dat, auth.length);	packet_send();	packet_write_wait();	/* Zero the buffer. */	(void) memset(auth.dat, 0, MAX_KTXT_LEN);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -