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

📄 ssh-agent.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 2 页
字号:
	sc_reader_id = buffer_get_string(&e->request, NULL);	pin = buffer_get_string(&e->request, NULL);	keys = sc_get_keys(sc_reader_id, pin);	xfree(sc_reader_id);	xfree(pin);	if (keys == NULL || keys[0] == NULL) {		error("sc_get_keys failed");		goto send;	}	for (i = 0; keys[i] != NULL; i++) {		k = keys[i];		version = k->type == KEY_RSA1 ? 1 : 2;		if ((id = lookup_identity(k, version)) != NULL) {			tab = idtab_lookup(version);			TAILQ_REMOVE(&tab->idlist, id, next);			tab->nentries--;			free_identity(id);			success = 1;		}		key_free(k);		keys[i] = NULL;	}	xfree(keys);send:	buffer_put_int(&e->output, 1);	buffer_put_char(&e->output,	    success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);}#endif /* SMARTCARD *//* dispatch incoming messages */static voidprocess_message(SocketEntry *e){	u_int msg_len;	u_int type;	u_char *cp;	/* kill dead keys */	reaper();	if (buffer_len(&e->input) < 5)		return;		/* Incomplete message. */	cp = buffer_ptr(&e->input);	msg_len = GET_32BIT(cp);	if (msg_len > 256 * 1024) {		shutdown(e->fd, SHUT_RDWR);		close(e->fd);		e->type = AUTH_UNUSED;		buffer_free(&e->input);		buffer_free(&e->output);		buffer_free(&e->request);		return;	}	if (buffer_len(&e->input) < msg_len + 4)		return;	/* move the current input to e->request */	buffer_consume(&e->input, 4);	buffer_clear(&e->request);	buffer_append(&e->request, buffer_ptr(&e->input), msg_len);	buffer_consume(&e->input, msg_len);	type = buffer_get_char(&e->request);	/* check wheter agent is locked */	if (locked && type != SSH_AGENTC_UNLOCK) {		buffer_clear(&e->request);		switch (type) {		case SSH_AGENTC_REQUEST_RSA_IDENTITIES:		case SSH2_AGENTC_REQUEST_IDENTITIES:			/* send empty lists */			no_identities(e, type);			break;		default:			/* send a fail message for all other request types */			buffer_put_int(&e->output, 1);			buffer_put_char(&e->output, SSH_AGENT_FAILURE);		}		return;	}	debug("type %d", type);	switch (type) {	case SSH_AGENTC_LOCK:	case SSH_AGENTC_UNLOCK:		process_lock_agent(e, type == SSH_AGENTC_LOCK);		break;	/* ssh1 */	case SSH_AGENTC_RSA_CHALLENGE:		process_authentication_challenge1(e);		break;	case SSH_AGENTC_REQUEST_RSA_IDENTITIES:		process_request_identities(e, 1);		break;	case SSH_AGENTC_ADD_RSA_IDENTITY:	case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:		process_add_identity(e, 1);		break;	case SSH_AGENTC_REMOVE_RSA_IDENTITY:		process_remove_identity(e, 1);		break;	case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:		process_remove_all_identities(e, 1);		break;	/* ssh2 */	case SSH2_AGENTC_SIGN_REQUEST:		process_sign_request2(e);		break;	case SSH2_AGENTC_REQUEST_IDENTITIES:		process_request_identities(e, 2);		break;	case SSH2_AGENTC_ADD_IDENTITY:	case SSH2_AGENTC_ADD_ID_CONSTRAINED:		process_add_identity(e, 2);		break;	case SSH2_AGENTC_REMOVE_IDENTITY:		process_remove_identity(e, 2);		break;	case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:		process_remove_all_identities(e, 2);		break;#ifdef SMARTCARD	case SSH_AGENTC_ADD_SMARTCARD_KEY:		process_add_smartcard_key(e);		break;	case SSH_AGENTC_REMOVE_SMARTCARD_KEY:		process_remove_smartcard_key(e);		break;#endif /* SMARTCARD */	default:		/* Unknown message.  Respond with failure. */		error("Unknown message %d", type);		buffer_clear(&e->request);		buffer_put_int(&e->output, 1);		buffer_put_char(&e->output, SSH_AGENT_FAILURE);		break;	}}static voidnew_socket(sock_type type, int fd){	u_int i, old_alloc;	if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)		error("fcntl O_NONBLOCK: %s", strerror(errno));	if (fd > max_fd)		max_fd = fd;	for (i = 0; i < sockets_alloc; i++)		if (sockets[i].type == AUTH_UNUSED) {			sockets[i].fd = fd;			sockets[i].type = type;			buffer_init(&sockets[i].input);			buffer_init(&sockets[i].output);			buffer_init(&sockets[i].request);			return;		}	old_alloc = sockets_alloc;	sockets_alloc += 10;	if (sockets)		sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));	else		sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));	for (i = old_alloc; i < sockets_alloc; i++)		sockets[i].type = AUTH_UNUSED;	sockets[old_alloc].type = type;	sockets[old_alloc].fd = fd;	buffer_init(&sockets[old_alloc].input);	buffer_init(&sockets[old_alloc].output);	buffer_init(&sockets[old_alloc].request);}static intprepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp){	u_int i, sz;	int n = 0;	for (i = 0; i < sockets_alloc; i++) {		switch (sockets[i].type) {		case AUTH_SOCKET:		case AUTH_CONNECTION:			n = MAX(n, sockets[i].fd);			break;		case AUTH_UNUSED:			break;		default:			fatal("Unknown socket type %d", sockets[i].type);			break;		}	}	sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);	if (*fdrp == NULL || sz > *nallocp) {		if (*fdrp)			xfree(*fdrp);		if (*fdwp)			xfree(*fdwp);		*fdrp = xmalloc(sz);		*fdwp = xmalloc(sz);		*nallocp = sz;	}	if (n < *fdl)		debug("XXX shrink: %d < %d", n, *fdl);	*fdl = n;	memset(*fdrp, 0, sz);	memset(*fdwp, 0, sz);	for (i = 0; i < sockets_alloc; i++) {		switch (sockets[i].type) {		case AUTH_SOCKET:		case AUTH_CONNECTION:			FD_SET(sockets[i].fd, *fdrp);			if (buffer_len(&sockets[i].output) > 0)				FD_SET(sockets[i].fd, *fdwp);			break;		default:			break;		}	}	return (1);}static voidafter_select(fd_set *readset, fd_set *writeset){	u_int i;	int len, sock;	socklen_t slen;	char buf[1024];	struct sockaddr_un sunaddr;	for (i = 0; i < sockets_alloc; i++)		switch (sockets[i].type) {		case AUTH_UNUSED:			break;		case AUTH_SOCKET:			if (FD_ISSET(sockets[i].fd, readset)) {				slen = sizeof(sunaddr);				sock = accept(sockets[i].fd,				    (struct sockaddr *) &sunaddr, &slen);				if (sock < 0) {					error("accept from AUTH_SOCKET: %s",					    strerror(errno));					break;				}				new_socket(AUTH_CONNECTION, sock);			}			break;		case AUTH_CONNECTION:			if (buffer_len(&sockets[i].output) > 0 &&			    FD_ISSET(sockets[i].fd, writeset)) {				do {					len = write(sockets[i].fd,					    buffer_ptr(&sockets[i].output),					    buffer_len(&sockets[i].output));					if (len == -1 && (errno == EAGAIN ||					    errno == EINTR))						continue;					break;				} while (1);				if (len <= 0) {					shutdown(sockets[i].fd, SHUT_RDWR);					close(sockets[i].fd);					sockets[i].type = AUTH_UNUSED;					buffer_free(&sockets[i].input);					buffer_free(&sockets[i].output);					buffer_free(&sockets[i].request);					break;				}				buffer_consume(&sockets[i].output, len);			}			if (FD_ISSET(sockets[i].fd, readset)) {				do {					len = read(sockets[i].fd, buf, sizeof(buf));					if (len == -1 && (errno == EAGAIN ||					    errno == EINTR))						continue;					break;				} while (1);				if (len <= 0) {					shutdown(sockets[i].fd, SHUT_RDWR);					close(sockets[i].fd);					sockets[i].type = AUTH_UNUSED;					buffer_free(&sockets[i].input);					buffer_free(&sockets[i].output);					buffer_free(&sockets[i].request);					break;				}				buffer_append(&sockets[i].input, buf, len);				process_message(&sockets[i]);			}			break;		default:			fatal("Unknown type %d", sockets[i].type);		}}static voidcleanup_socket(void *p){	if (socket_name[0])		unlink(socket_name);	if (socket_dir[0])		rmdir(socket_dir);}static voidcleanup_exit(int i){	cleanup_socket(NULL);	exit(i);}static voidcleanup_handler(int sig){	cleanup_socket(NULL);	_exit(2);}static voidcheck_parent_exists(int sig){	int save_errno = errno;	if (parent_pid != -1 && kill(parent_pid, 0) < 0) {		/* printf("Parent has died - Authentication agent exiting.\n"); */		cleanup_handler(sig); /* safe */	}	signal(SIGALRM, check_parent_exists);	alarm(10);	errno = save_errno;}static voidusage(void){	fprintf(stderr, "Usage: %s [options] [command [args ...]]\n",	    __progname);	fprintf(stderr, "Options:\n");	fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");	fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");	fprintf(stderr, "  -k          Kill the current agent.\n");	fprintf(stderr, "  -d          Debug mode.\n");	fprintf(stderr, "  -a socket   Bind agent socket to given name.\n");	exit(1);}intmain(int ac, char **av){	int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;	struct sockaddr_un sunaddr;#ifdef HAVE_SETRLIMIT	struct rlimit rlim;#endif#ifdef HAVE_CYGWIN	int prev_mask;#endif	pid_t pid;	char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];	char *agentsocket = NULL;	extern int optind;	fd_set *readsetp = NULL, *writesetp = NULL;	SSLeay_add_all_algorithms();	__progname = get_progname(av[0]);	init_rng();	seed_rng();#ifdef __GNU_LIBRARY__	while ((ch = getopt(ac, av, "+cdksa:")) != -1) {#else /* __GNU_LIBRARY__ */	while ((ch = getopt(ac, av, "cdksa:")) != -1) {#endif /* __GNU_LIBRARY__ */		switch (ch) {		case 'c':			if (s_flag)				usage();			c_flag++;			break;		case 'k':			k_flag++;			break;		case 's':			if (c_flag)				usage();			s_flag++;			break;		case 'd':			if (d_flag)				usage();			d_flag++;			break;		case 'a':			agentsocket = optarg;			break;		default:			usage();		}	}	ac -= optind;	av += optind;	if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))		usage();	if (ac == 0 && !c_flag && !s_flag) {		shell = getenv("SHELL");		if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)			c_flag = 1;	}	if (k_flag) {		pidstr = getenv(SSH_AGENTPID_ENV_NAME);		if (pidstr == NULL) {			fprintf(stderr, "%s not set, cannot kill agent\n",			    SSH_AGENTPID_ENV_NAME);			exit(1);		}		pid = atoi(pidstr);		if (pid < 1) {			fprintf(stderr, "%s=\"%s\", which is not a good PID\n",			    SSH_AGENTPID_ENV_NAME, pidstr);			exit(1);		}		if (kill(pid, SIGTERM) == -1) {			perror("kill");			exit(1);		}		format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";		printf(format, SSH_AUTHSOCKET_ENV_NAME);		printf(format, SSH_AGENTPID_ENV_NAME);		printf("echo Agent pid %ld killed;\n", (long)pid);		exit(0);	}	parent_pid = getpid();	if (agentsocket == NULL) {		/* Create private directory for agent socket */		strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);		if (mkdtemp(socket_dir) == NULL) {			perror("mkdtemp: private socket dir");			exit(1);		}		snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,		    (long)parent_pid);	} else {		/* Try to use specified agent socket */		socket_dir[0] = '\0';		strlcpy(socket_name, agentsocket, sizeof socket_name);	}	/*	 * Create socket early so it will exist before command gets run from	 * the parent.	 */	sock = socket(AF_UNIX, SOCK_STREAM, 0);	if (sock < 0) {		perror("socket");		cleanup_exit(1);	}	memset(&sunaddr, 0, sizeof(sunaddr));	sunaddr.sun_family = AF_UNIX;	strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));#ifdef HAVE_CYGWIN	prev_mask = umask(0177);#endif	if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {		perror("bind");#ifdef HAVE_CYGWIN		umask(prev_mask);#endif		cleanup_exit(1);	}#ifdef HAVE_CYGWIN	umask(prev_mask);#endif	if (listen(sock, 5) < 0) {		perror("listen");		cleanup_exit(1);	}	/*	 * Fork, and have the parent execute the command, if any, or present	 * the socket data.  The child continues as the authentication agent.	 */	if (d_flag) {		log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);		format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";		printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,		    SSH_AUTHSOCKET_ENV_NAME);		printf("echo Agent pid %ld;\n", (long)parent_pid);		goto skip;	}	pid = fork();	if (pid == -1) {		perror("fork");		cleanup_exit(1);	}	if (pid != 0) {		/* Parent - execute the given command. */		close(sock);		snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);		if (ac == 0) {			format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";			printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,			    SSH_AUTHSOCKET_ENV_NAME);			printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,			    SSH_AGENTPID_ENV_NAME);			printf("echo Agent pid %ld;\n", (long)pid);			exit(0);		}		if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||		    setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {			perror("setenv");			exit(1);		}		execvp(av[0], av);		perror(av[0]);		exit(1);	}	/* child */	log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);	if (setsid() == -1) {		error("setsid: %s", strerror(errno));		cleanup_exit(1);	}	(void)chdir("/");	close(0);	close(1);	close(2);#ifdef HAVE_SETRLIMIT	/* deny core dumps, since memory contains unencrypted private keys */	rlim.rlim_cur = rlim.rlim_max = 0;	if (setrlimit(RLIMIT_CORE, &rlim) < 0) {		error("setrlimit RLIMIT_CORE: %s", strerror(errno));		cleanup_exit(1);	}#endifskip:	fatal_add_cleanup(cleanup_socket, NULL);	new_socket(AUTH_SOCKET, sock);	if (ac > 0) {		signal(SIGALRM, check_parent_exists);		alarm(10);	}	idtab_init();	if (!d_flag)		signal(SIGINT, SIG_IGN);	signal(SIGPIPE, SIG_IGN);	signal(SIGHUP, cleanup_handler);	signal(SIGTERM, cleanup_handler);	nalloc = 0;	while (1) {		prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);		if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {			if (errno == EINTR)				continue;			fatal("select: %s", strerror(errno));		}		after_select(readsetp, writesetp);	}	/* NOTREACHED */}

⌨️ 快捷键说明

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