00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "vsl_ssh.h"
00015 #include "vsl_util.h"
00016 #include "vsl.h"
00017 #include <sys/types.h>
00018 #include <sys/wait.h>
00019 #include <netdb.h>
00020 #include <sys/select.h>
00021 #include <fcntl.h>
00022
00023
00024 struct ssh_msg_secret {
00025 char magic[P_MAGIC_SIZE];
00026 unsigned char secret[VSL_KEYLEN];
00027 };
00028
00029
00030 struct ssh_msg_port {
00031 char magic[P_MAGIC_SIZE];
00032 uint32_t port;
00033 };
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 int ssh_fork(vsl_sock* sock, const char* host, const char* user,
00052 const char* cmd, int argc, const char* const* argv) {
00053
00054 LOG("attempting to fork ssh...");
00055
00056
00057 int stdin_fd[2],
00058 stderr_fd[2],
00059 stdout_fd[2];
00060 if ( pipe(stdin_fd) == -1 ||
00061 pipe(stderr_fd) == -1 ||
00062 pipe(stdout_fd) == -1)
00063 LOGFAIL(VSL_ERRNO, "pipe failed: %s", strerror(err));
00064
00065
00066 pid_t pid;
00067 if ( (pid = fork()) == 0 ) {
00068
00069
00070 if ( close(stdin_fd[1]) != 0)
00071 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00072 if ( stdin_fd[0] != STDIN_FILENO ) {
00073 if ( dup2(stdin_fd[0], STDIN_FILENO) != STDIN_FILENO ) {
00074 LOG("(child) dup2 failed: %s!", strerror(errno));
00075 exit(VSL_TEMP);
00076 }
00077 if ( close(stdin_fd[0]) != 0)
00078 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00079 }
00080
00081
00082 if ( close(stdout_fd[0]) != 0)
00083 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00084 if ( stdout_fd[1] != STDOUT_FILENO) {
00085 if ( dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO ) {
00086 LOG("(child) dup2 failed: %s", strerror(errno));
00087 exit(VSL_TEMP);
00088 }
00089 if ( close(stdout_fd[1]) != 0)
00090 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00091 }
00092
00093
00094 if ( close(stderr_fd[0]) != 0)
00095 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00096 if ( stderr_fd[1] != STDERR_FILENO ) {
00097 if ( dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO ) {
00098 LOG("(child) dup2 failed: %s", strerror(errno));
00099 exit(VSL_TEMP);
00100 }
00101 if ( close(stderr_fd[1]) != 0)
00102 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00103 }
00104
00105
00106 const char *tot_argv[7 + argc];
00107 int cur = 0;
00108 tot_argv[cur++] = "ssh";
00109 tot_argv[cur++] = "-T";
00110 if (user != NULL) {
00111 tot_argv[cur++] = "-l";
00112 tot_argv[cur++] = user;
00113 }
00114 tot_argv[cur++] = host;
00115 tot_argv[cur++] = cmd;
00116 for (int i=0; i < argc; i++)
00117 tot_argv[cur++] = argv[i];
00118 tot_argv[cur++] = NULL;
00119
00120 LOG("(child) exec'ing ssh...");
00121 execvp("ssh", (char *const*) tot_argv);
00122 LOG("(child) exec failed: %s", strerror(errno));
00123 exit(VSL_PERM);
00124 }
00125
00126 else if(pid == -1)
00127 LOGFAIL(VSL_ERRNO, "fork failed: %s", strerror(err));
00128
00129
00130 if ( close(stdin_fd[0]) != 0 ||
00131 close(stdout_fd[1]) != 0 ||
00132 close(stderr_fd[1]) != 0 )
00133 LOGFAIL(VSL_ERRNO, "can't close pipe: %s!", strerror(errno));
00134 sock->ssh_pid = pid;
00135 sock->ssh_stdin_fd = stdin_fd[1];
00136 sock->ssh_stdout_fd = stdout_fd[0];
00137 sock->ssh_stderr_fd = stderr_fd[0];
00138
00139
00140 if (!is_blocking(sock)) {
00141 long fdflags;
00142 if ( (fdflags = fcntl(sock->ssh_stdin_fd, F_GETFL, 0)) < 0 ||
00143 fcntl(sock->ssh_stdin_fd, F_SETFL, fdflags | O_NONBLOCK) < 0 ||
00144 (fdflags = fcntl(sock->ssh_stdout_fd, F_GETFL, 0)) < 0 ||
00145 fcntl(sock->ssh_stdout_fd, F_SETFL, fdflags | O_NONBLOCK) < 0 ||
00146 (fdflags = fcntl(sock->ssh_stderr_fd, F_GETFL, 0)) < 0 ||
00147 fcntl(sock->ssh_stderr_fd, F_SETFL, fdflags | O_NONBLOCK) < 0 )
00148 LOGFAIL(VSL_ERRNO, "fcntl failed: %s", strerror(err));
00149 }
00150
00151
00152 LOG("ssh forked successfully.");
00153 return(0);
00154 }
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 int ssh_send_secret (vsl_sock* sock, const unsigned char* secret) {
00168 LOG("attempting to send shared secret over ssh...");
00169 LOG("secret is " KEY_STR, KEY_VEC(secret));
00170
00171
00172 struct ssh_msg_secret msg;
00173 FILL_MAGIC(msg.magic);
00174 memcpy((void *) msg.secret, (void*) secret, VSL_KEYLEN);
00175
00176
00177 size_t buflen;
00178 void *buf;
00179 if ( (buf = write_objs(&buflen,
00180 (void*) &msg.magic, sizeof(msg.magic),
00181 (void*) &msg.secret, sizeof(msg.secret),
00182 NULL)) == NULL)
00183 LOGFAIL(VSL_ERRNO, "malloc failed: %s", strerror(err));
00184
00185
00186 if ( signal(SIGPIPE, SIG_IGN) == SIG_ERR )
00187 LOGFATAL("cannot ignore sigpipe!");
00188
00189
00190 if(write(sock->ssh_stdin_fd, buf, buflen) != buflen) {
00191 free(buf);
00192 if(!is_blocking(sock) &&
00193 errno == EAGAIN)
00194 return(VFER_INPROGRESS);
00195 LOGFAIL(VSL_ERRNO, "write failed: %s", strerror(err));
00196 }
00197 free(buf);
00198
00199
00200 if ( close(sock->ssh_stdin_fd) != 0 )
00201 LOGFAIL(VSL_ERRNO, "close failed: %s", strerror(err));
00202
00203 LOG("shared secret sent over ssh.");
00204
00205 return(0);
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 int ssh_read_port (vsl_sock* sock, int* port) {
00221 LOG("attempting to get port number...");
00222
00223
00224 ssize_t ret;
00225 struct ssh_msg_port msg;
00226 unsigned char buf[sizeof msg];
00227 if ( (ret = read(sock->ssh_stdout_fd, (void*) buf, sizeof(msg))) < 0) {
00228 if (errno == EAGAIN)
00229 return VFER_INPROGRESS;
00230 else
00231 LOGFAIL(VSL_ERRNO, "read failed: %s", strerror(errno));
00232 }
00233
00234
00235 if ( read_objs(buf, ret,
00236 (void*) &msg.magic, sizeof(msg.magic),
00237 (void*) &msg.port, sizeof(msg.port),
00238 NULL) == NULL )
00239 LOGFAIL(VSL_BADPROT, "received message too short!");
00240
00241 if(!CHECK_MAGIC(msg.magic))
00242 LOGFAIL(VSL_BADPROT, "invalid message received");
00243 *port = ntohl(msg.port);
00244
00245 LOG("read port nr. %d.", *port);
00246 return 0;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 int ssh_close (vsl_sock* sock, char* errmsg) {
00267 int retval = 0;
00268
00269 LOG("attempting to read error message...");
00270
00271
00272 int ret;
00273 if ( (ret = read(sock->ssh_stderr_fd, (void*) errmsg, 512)) != 0 ) {
00274 if (ret == -1 &&
00275 errno == EAGAIN) {
00276 LOG("call would block, returning.");
00277 return VFER_INPROGRESS;
00278 }
00279 else if (ret == -1)
00280 LOGFAIL(VSL_ERRNO, "read failed: %s", strerror(errno));
00281 errmsg[ret] = '\0';
00282 LOG("got error message: %s.", errmsg);
00283 retval = VSL_SSHF;
00284 }
00285
00286
00287
00288
00289
00290
00291 if ( close(sock->ssh_stdin_fd) != 0 ||
00292 close(sock->ssh_stdout_fd) != 0 ||
00293 close(sock->ssh_stderr_fd) != 0 )
00294
00295 ;
00296
00297
00298
00299 int pidstat;
00300 if ( sock->ssh_pid == 0 ) {
00301 LOG("using existing ssh exit status...");
00302 pidstat = sock->ssh_pid_stat;
00303 }
00304 else {
00305
00306 LOG("attempting to wait for ssh process...");
00307 if(!is_blocking(sock)) {
00308 if( (ret=waitpid(sock->ssh_pid, &pidstat, WNOHANG)) == 0) {
00309 LOG("call would block, returning.");
00310 return VFER_INPROGRESS;
00311 }
00312 }
00313 else
00314 ret = waitpid(sock->ssh_pid, &pidstat, 0);
00315
00316 if(ret != sock->ssh_pid)
00317 LOGFAIL(VSL_ERRNO, "waitpid failed: %s", strerror(err));
00318 }
00319
00320
00321 if( !WIFEXITED(pidstat) )
00322 LOGFAIL(VSL_SSHF, "ssh process aborted.");
00323
00324 if(WEXITSTATUS(pidstat) == 255) {
00325 LOGFAIL(VSL_SSHF, "ssh process failed!");
00326 }
00327 else if (WEXITSTATUS(pidstat) == VSL_TEMP ||
00328 WEXITSTATUS(pidstat) == VSL_PERM ) {
00329 LOGFAIL(WEXITSTATUS(pidstat), "server signaled error!");
00330 }
00331 else if(WEXITSTATUS(pidstat) != 0 )
00332 LOGFAIL(VSL_BADPROT, "invalid exit code!");
00333
00334 LOG("ssh connection closed.");
00335 return retval;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 int ssh_vfer_connect(vsl_sock* sock, const char* host, int port) {
00350
00351 LOG("attempting vfer_connect to %s:%d...", host, port);
00352 int ret;
00353
00354
00355 struct sockaddr_in client_sa;
00356 bzero((char*)(&client_sa), sizeof(client_sa));
00357 client_sa.sin_port = htons(0);
00358 client_sa.sin_family = AF_INET;
00359
00360
00361 if ( (ret=vfer_bind(sock->vfd, (struct sockaddr*) &client_sa, sizeof(client_sa))) < 0)
00362 LOGFATAL("vfer_bind failed [%s]", vfer_errortext(ret));
00363
00364
00365 char remote_ip[INET_ADDRSTRLEN];
00366 struct hostent* h;
00367 if ((h = gethostbyname(host)) == NULL)
00368 LOGFAIL(VSL_ERRNO, "can't get remote ip: %s", strerror(errno));
00369 if (h->h_addr_list != 0) {
00370 inet_ntop(h->h_addrtype, (h->h_addr_list)[0], remote_ip, sizeof(remote_ip));
00371 }
00372
00373
00374 struct sockaddr_in server_sa;
00375 bzero((char*)(&server_sa), sizeof(server_sa));
00376 server_sa.sin_family = AF_INET;
00377 server_sa.sin_port = htons(port);
00378 if (inet_pton(AF_INET, remote_ip, &server_sa.sin_addr) != 1)
00379 LOGFAIL(VSL_ERRNO, "inet_pton failed: %s", strerror(errno));
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 if ((ret = vfer_connect(sock->vfd, (struct sockaddr*) &server_sa,
00394 sizeof(server_sa))) != 0 &&
00395 ret != VFER_INPROGRESS )
00396 LOGFATAL("vfer_connect failed [%s]", vfer_errortext(ret));
00397 LOG("connection established.");
00398
00399
00400 return 0;
00401 }
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 int ssh_read_secret (unsigned char* secret) {
00415 LOG("attempting to get secret...");
00416
00417
00418 ssize_t ret;
00419 struct ssh_msg_secret msg;
00420 unsigned char buf[sizeof msg];
00421 if ( (ret = read(STDIN_FILENO, (void*) buf, sizeof(msg))) < 0) {
00422 if (errno == EAGAIN)
00423 return VFER_INPROGRESS;
00424 else
00425 LOGFAIL(VSL_ERRNO, "read failed: %s", strerror(errno));
00426 }
00427
00428
00429 if ( read_objs(buf, ret,
00430 (void*) &msg.magic, sizeof(msg.magic),
00431 (void*) &msg.secret, sizeof(msg.secret),
00432 NULL) == NULL )
00433 LOGFAIL(VSL_BADPROT, "received message too short!");
00434
00435 if(!CHECK_MAGIC(msg.magic))
00436 LOGFAIL(VSL_BADPROT, "invalid message received!");
00437 memcpy((void*) secret, (void*) msg.secret, VSL_KEYLEN);
00438
00439 LOG("got secret " KEY_STR ".", KEY_VEC(secret));
00440 return 0;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 int ssh_vfer_listen (vsl_sock* sock, int* port) {
00457 LOG("attempting to listen...");
00458
00459 struct sockaddr_in sa;
00460 socklen_t len = sizeof(sa);
00461 int ret;
00462
00463 bzero((char*)(&sa), sizeof(sa));
00464 sa.sin_family = AF_INET;
00465 sa.sin_addr.s_addr = htonl(INADDR_ANY);
00466 sa.sin_port = htons(0);
00467
00468 if ((ret = vfer_bind(sock->vfd, (struct sockaddr*) &sa, sizeof(sa))) != 0)
00469 LOGFATAL("vfer_bind failed: %s!", vfer_errortext(ret));
00470
00471 if ((ret = vfer_listen(sock->vfd, 3)) != 0)
00472 LOGFATAL("vfer_listen failed: %s!", vfer_errortext(ret));
00473
00474 if ((ret = vfer_getsockname(sock->vfd, (struct sockaddr*) &sa, &len)) != 0)
00475 LOGFATAL("vfer_getsockname failed: %s!", vfer_errortext(ret));
00476
00477 *port = ntohs(sa.sin_port);
00478
00479 LOG("listening on port %d.", *port);
00480 return 0;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 int ssh_send_port (int port) {
00494 LOG("attempting to send port %d...", port);
00495
00496
00497 struct ssh_msg_port msg;
00498 FILL_MAGIC(msg.magic);
00499 msg.port = htonl(port);
00500
00501
00502 size_t buflen;
00503 void *buf;
00504 if ( (buf = write_objs(&buflen,
00505 (void*) &msg.magic, sizeof(msg.magic),
00506 (void*) &msg.port, sizeof(msg.port),
00507 NULL)) == NULL)
00508 LOGFAIL(VSL_ERRNO, "malloc failed: %s", strerror(err));
00509
00510
00511 if(write(STDOUT_FILENO, (void*) buf, buflen) != buflen) {
00512 free(buf);
00513 LOGFAIL(VSL_ERRNO, "write failed: %s", strerror(errno));
00514 }
00515 free(buf);
00516
00517 LOG("port message sent.");
00518 return 0;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 int ssh_vfer_accept (vsl_sock* sock) {
00532 LOG("attempting to accept vfer connection...");
00533
00534
00535 int ret;
00536 if ( (ret = vfer_setsockopt(sock->vfd, VFERSO_ACCEPTTIMEOUT,
00537 &((int) { 60000000 } ), sizeof(int))) != 0)
00538 LOGFATAL("can't set socket state: %s!", vfer_errortext(ret));
00539
00540
00541 struct sockaddr_in sa;
00542 bzero((char*)(&sa), sizeof(sa));
00543 socklen_t len = sizeof(sa);
00544 int vfd;
00545 if ((vfd = vfer_accept(sock->vfd, (struct sockaddr*) &sa, &len)) == VFER_TIMEOUT)
00546 LOGFAIL(vfd, "timed out, returning.");
00547 else if ( vfd < 0 )
00548 LOGFATAL("vfer_accept failed: %s!", vfer_errortext(vfd));
00549 sock->vfd = vfd;
00550
00551 LOG("Done.");
00552 return 0;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562 int ssh_daemonize (void) {
00563 LOG("daemonizing...");
00564 if (daemon(0,0) != 0 )
00565 LOGFAIL(VSL_ERRNO, "daemon failed: %s!", strerror(errno));
00566 return 0;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575