OSDN Git Service

cleanup
[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 2012-01-05 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         LOG(LOG_ERR, "null input");
67         return -1;
68     }
69
70     /* socket */
71     if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair) == -1) {
72         LOG(LOG_ERR, "socketpair() fail");
73         goto err;
74     }
75
76     /* fork */
77     if ((pid = fork()) == -1) {
78         LOG(LOG_ERR, "fork() fail");
79         goto err_close;
80     }
81     if (pid == 0) {
82         /* child process */
83         char *arguments[16];
84         int arg_idx = 0;
85         char identity_string[PATH_MAX + /* "IdentityFile " */ 13];
86
87         // these belong to father
88         close(socket_pair[0]);
89         close(0);
90         close(1);
91
92         // replace stdin and stdout with the socket end
93         dup2(socket_pair[1], 0);
94         dup2(socket_pair[1], 1);
95         close(socket_pair[1]);  // no longer needed
96
97         arguments[arg_idx++] = "ssh";
98         arguments[arg_idx++] = "-2";
99         if (ssh_username != NULL) {
100             arguments[arg_idx++] = "-l";
101             arguments[arg_idx++] = ssh_username;
102         }
103         if (ssh_port != NULL) {
104             arguments[arg_idx++] = "-p";
105             arguments[arg_idx++] = ssh_port;
106         }
107         /* // should be specified in the ssh_conf file 
108         arguments[arg_idx++] = "-o";
109         arguments[arg_idx++] = "BatchMode yes";
110         */
111         if (key_file != NULL) {
112             snprintf(identity_string, PATH_MAX + 13, "IdentityFile %s", key_file);
113             arguments[arg_idx++] = "-o";
114             arguments[arg_idx++] = identity_string;
115         }
116         arguments[arg_idx++] = host;
117         arguments[arg_idx++] = ptsc_command;
118 #if 0
119         // TODO
120         /* Sync verbose level between verifier and collector? */
121         if (verbose_sync) {
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         LOG(LOG_ERR, "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