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

📄 authfd.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * Functions for connecting the local authentication agent. * * 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". * * SSH2 implementation, * Copyright (c) 2000 Markus Friedl.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: authfd.c,v 1.55 2002/06/19 00:27:55 deraadt Exp $");#include <openssl/evp.h>#include "ssh.h"#include "rsa.h"#include "buffer.h"#include "bufaux.h"#include "xmalloc.h"#include "getput.h"#include "key.h"#include "authfd.h"#include "cipher.h"#include "kex.h"#include "compat.h"#include "log.h"#include "atomicio.h"/* helper */int	decode_reply(int type);/* macro to check for "agent failure" message */#define agent_failed(x) \    ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \    (x == SSH2_AGENT_FAILURE))/* Returns the number of the authentication fd, or -1 if there is none. */intssh_get_authentication_socket(void){	const char *authsocket;	int sock;	struct sockaddr_un sunaddr;	authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);	if (!authsocket)		return -1;	sunaddr.sun_family = AF_UNIX;	strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));	sock = socket(AF_UNIX, SOCK_STREAM, 0);	if (sock < 0)		return -1;	/* close on exec */	if (fcntl(sock, F_SETFD, 1) == -1) {		close(sock);		return -1;	}	if (connect(sock, (struct sockaddr *) &sunaddr, sizeof sunaddr) < 0) {		close(sock);		return -1;	}	return sock;}static intssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply){	int l, len;	char buf[1024];	/* Get the length of the message, and format it in the buffer. */	len = buffer_len(request);	PUT_32BIT(buf, len);	/* Send the length and then the packet to the agent. */	if (atomicio(write, auth->fd, buf, 4) != 4 ||	    atomicio(write, auth->fd, buffer_ptr(request),	    buffer_len(request)) != buffer_len(request)) {		error("Error writing to authentication socket.");		return 0;	}	/*	 * Wait for response from the agent.  First read the length of the	 * response packet.	 */	len = 4;	while (len > 0) {		l = read(auth->fd, buf + 4 - len, len);		if (l == -1 && (errno == EAGAIN || errno == EINTR))			continue;		if (l <= 0) {			error("Error reading response length from authentication socket.");			return 0;		}		len -= l;	}	/* Extract the length, and check it for sanity. */	len = GET_32BIT(buf);	if (len > 256 * 1024)		fatal("Authentication response too long: %d", len);	/* Read the rest of the response in to the buffer. */	buffer_clear(reply);	while (len > 0) {		l = len;		if (l > sizeof(buf))			l = sizeof(buf);		l = read(auth->fd, buf, l);		if (l == -1 && (errno == EAGAIN || errno == EINTR))			continue;		if (l <= 0) {			error("Error reading response from authentication socket.");			return 0;		}		buffer_append(reply, (char *) buf, l);		len -= l;	}	return 1;}/* * Closes the agent socket if it should be closed (depends on how it was * obtained).  The argument must have been returned by * ssh_get_authentication_socket(). */voidssh_close_authentication_socket(int sock){	if (getenv(SSH_AUTHSOCKET_ENV_NAME))		close(sock);}/* * Opens and connects a private socket for communication with the * authentication agent.  Returns the file descriptor (which must be * shut down and closed by the caller when no longer needed). * Returns NULL if an error occurred and the connection could not be * opened. */AuthenticationConnection *ssh_get_authentication_connection(void){	AuthenticationConnection *auth;	int sock;	sock = ssh_get_authentication_socket();	/*	 * Fail if we couldn't obtain a connection.  This happens if we	 * exited due to a timeout.	 */	if (sock < 0)		return NULL;	auth = xmalloc(sizeof(*auth));	auth->fd = sock;	buffer_init(&auth->identities);	auth->howmany = 0;	return auth;}/* * Closes the connection to the authentication agent and frees any associated * memory. */voidssh_close_authentication_connection(AuthenticationConnection *auth){	buffer_free(&auth->identities);	close(auth->fd);	xfree(auth);}/* Lock/unlock agent */intssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password){	int type;	Buffer msg;	buffer_init(&msg);	buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK);	buffer_put_cstring(&msg, password);	if (ssh_request_reply(auth, &msg, &msg) == 0) {		buffer_free(&msg);		return 0;	}	type = buffer_get_char(&msg);	buffer_free(&msg);	return decode_reply(type);}/* * Returns the first authentication identity held by the agent. */intssh_get_num_identities(AuthenticationConnection *auth, int version){	int type, code1 = 0, code2 = 0;	Buffer request;	switch (version) {	case 1:		code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;		code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;		break;	case 2:		code1 = SSH2_AGENTC_REQUEST_IDENTITIES;		code2 = SSH2_AGENT_IDENTITIES_ANSWER;		break;	default:		return 0;	}	/*	 * Send a message to the agent requesting for a list of the	 * identities it can represent.	 */	buffer_init(&request);	buffer_put_char(&request, code1);	buffer_clear(&auth->identities);	if (ssh_request_reply(auth, &request, &auth->identities) == 0) {		buffer_free(&request);		return 0;	}	buffer_free(&request);	/* Get message type, and verify that we got a proper answer. */	type = buffer_get_char(&auth->identities);	if (agent_failed(type)) {		return 0;	} else if (type != code2) {		fatal("Bad authentication reply message type: %d", type);	}	/* Get the number of entries in the response and check it for sanity. */	auth->howmany = buffer_get_int(&auth->identities);	if (auth->howmany > 1024)		fatal("Too many identities in authentication reply: %d",		    auth->howmany);	return auth->howmany;}Key *ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version){	/* get number of identities and return the first entry (if any). */	if (ssh_get_num_identities(auth, version) > 0)		return ssh_get_next_identity(auth, comment, version);	return NULL;}Key *ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version){	u_int bits;	u_char *blob;	u_int blen;	Key *key = NULL;	/* Return failure if no more entries. */	if (auth->howmany <= 0)		return NULL;	/*	 * Get the next entry from the packet.  These will abort with a fatal	 * error if the packet is too short or contains corrupt data.	 */	switch (version) {	case 1:		key = key_new(KEY_RSA1);		bits = buffer_get_int(&auth->identities);		buffer_get_bignum(&auth->identities, key->rsa->e);		buffer_get_bignum(&auth->identities, key->rsa->n);		*comment = buffer_get_string(&auth->identities, NULL);		if (bits != BN_num_bits(key->rsa->n))			log("Warning: identity keysize mismatch: actual %d, announced %u",

⌨️ 快捷键说明

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