OSDN Git Service

7b3a894bbdc51753f005874ec4d6c1fff5fa22fc
[openpts/openpts.git] / src / ssh.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
4  * The Initial Developer of the Original Code is International
5  * Business Machines Corporation. Portions created by IBM
6  * Corporation are Copyright (C) 2011 International Business
7  * Machines Corporation. All Rights Reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the Common Public License as published by
11  * IBM Corporation; either version 1 of the License, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * Common Public License for more details.
18  *
19  * You should have received a copy of the Common Public License
20  * along with this program; if not, a copy can be viewed at
21  * http://www.opensource.org/licenses/cpl1.0.php.
22  */
23
24 /**
25  * \file src/ssh.c
26  * \brief SSH conenction
27  * @author Olivier Valentin <olivier.valentin@us.ibm.com>
28  * @author Alexandre Ratchov <alexandre.ratchov@bull.net>
29  * @date 2010-03-31
30  * cleanup 2011-12-31 SM
31  *
32  */
33
34 #include <unistd.h>
35 #include <limits.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <fcntl.h>
40 #include <sys/socket.h>
41
42 #include <openpts.h>
43
44 /* chanegd by unit test */
45 char *ptsc_command = "/usr/sbin/ptsc -m";
46
47 /** 
48  * ssh_connect
49  *
50  * opens a communication channel (a socket) to a target using ssh.
51  * 
52  * @param host host name of the target. Is used as the SSH host name parameter.
53  * @param ssh_username If not NULL, specifies the SSH user name to login as
54  *        (defaults to the current user).
55  * @param ssh_port If not 0, specifiesd the port of the remote SSH daemon.
56  * @param key_file If not NULL, specifies the key to use.
57  * @param socket Filed with the result socket. Use it for later communication.
58  * @result the PID of the child SSH process or -1 in case of an error.
59  */
60 pid_t ssh_connect(char *host, char *ssh_username, char *ssh_port, char *key_file, int *socket) {
61     pid_t pid;
62     int socket_pair[2];  // socket[1] is the SSH side
63
64     /* check */
65     if (host == NULL) {
66         ERROR("null input");
67         return -1;
68     }
69
70
71     /* socket */
72     if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1) {
73         ERROR("socketpair() fail");
74         goto err;
75     }
76
77     if ((pid = fork()) == -1) {
78         ERROR("fork() fail");
79         goto err_close;
80     }
81
82     if (pid == 0) {
83         // child process
84         char *arguments[16];
85         int arg_idx = 0;
86         char identity_string[PATH_MAX + /* "IdentityFile " */ 13];
87
88         // these belong to father
89         close(socket_pair[0]);
90         close(0);
91         close(1);
92
93         // replace stdin and stdout with the socket end
94         dup2(socket_pair[1], 0);
95         dup2(socket_pair[1], 1);
96         close(socket_pair[1]);  // no longer needed
97
98         arguments[arg_idx++] = "ssh";
99         arguments[arg_idx++] = "-2";
100         if (ssh_username != NULL) {
101             arguments[arg_idx++] = "-l";
102             arguments[arg_idx++] = ssh_username;
103         }
104         if (ssh_port != NULL) {
105             arguments[arg_idx++] = "-p";
106             arguments[arg_idx++] = ssh_port;
107         }
108         /* // should be specified in the ssh_conf file 
109         arguments[arg_idx++] = "-o";
110         arguments[arg_idx++] = "BatchMode yes";
111         */
112         if (key_file != NULL) {
113             snprintf(identity_string, PATH_MAX + 13, "IdentityFile %s", key_file);
114             arguments[arg_idx++] = "-o";
115             arguments[arg_idx++] = identity_string;
116         }
117         arguments[arg_idx++] = host;
118         arguments[arg_idx++] = ptsc_command;
119 #if 0
120         /* Sync verbose level between verifier and collector? */
121         // {
122            int verboseLevel;
123             for ( verboseLevel = 0; (verboseLevel < getVerbosity()) && (arg_idx < 15); verboseLevel++ ) {
124                 arguments[arg_idx++] = "-v";
125             }
126         // }
127 #endif
128         arguments[arg_idx++] = NULL;
129
130         DEBUG("ptsc_command %s\n", ptsc_command);
131
132         execvp("ssh", arguments);
133         ERROR("execvp(ssh)");
134         exit(1);
135     }
136
137     close(socket_pair[1]);
138     *socket = socket_pair[0];
139
140     fcntl(*socket, F_SETFD, FD_CLOEXEC);
141
142     // success
143     return pid;
144
145   err_close:
146     close(socket_pair[0]);
147     close(socket_pair[1]);
148   err:
149     return -1;
150 }
151