~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to cmd/osspartysh/osspartysh.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: "Reverse telnet" helper utility for OSS technical support
 
3
 *
 
4
 * Description:
 
5
 * The osspartysh program is an utility that permits safe access to the
 
6
 * customer systems by the OSS support staff.
 
7
 *
 
8
 * Unlike usual ssh/telnet access this program works in revewrse way. The
 
9
 * person who gives technical support can establish a termibal server using
 
10
 * osspartysh -d -p <TCP port>. The client can then connect to this
 
11
 * terminal server program by executing osspartysh -h <the support host> -p <port>.
 
12
 * Outgoing TCP connections can easily pass usual firewall and NAT settings
 
13
 * which makes establishing the connection very easy. After the connection is 
 
14
 * open both sides can type commands and see what happens in the system. If
 
15
 * the customer thiks the tech suport guy is doing something too dangerous he
 
16
 * can always hit ^C or ^Z and unplug the ethernet connector.
 
17
 */
 
18
/*
 
19
 *
 
20
 * This file is part of Open Sound System.
 
21
 *
 
22
 * Copyright (C) 4Front Technologies 1996-2008.
 
23
 *
 
24
 * This this source file is released under GPL v2 license (no other versions).
 
25
 * See the COPYING file included in the main directory of this source
 
26
 * distribution for the license terms and conditions.
 
27
 *
 
28
 */
 
29
 
 
30
#include <stdio.h>
 
31
#include <sys/types.h>
 
32
#include <sys/stat.h>
 
33
#include <sys/socket.h>
 
34
#include <sys/select.h>
 
35
#include <sys/wait.h>
 
36
#include <netinet/in.h>
 
37
#include <netinet/tcp.h>
 
38
#include <arpa/inet.h>
 
39
#include <netdb.h>
 
40
#include <stdlib.h>
 
41
#include <string.h>
 
42
#include <unistd.h>
 
43
#include <termios.h>
 
44
#include <fcntl.h>
 
45
#ifdef __FreeBSD__
 
46
#include <libutil.h>
 
47
#else
 
48
#include <pty.h>
 
49
#include <utmp.h>
 
50
#endif
 
51
#include <errno.h>
 
52
 
 
53
#define PARTYSH_MAGIC           "ParTySH"
 
54
#define PARTYSH_VERSION         "0100"          // 1.0
 
55
#define PARTYSH_HDRSIZE         250
 
56
 
 
57
int localfd=0;
 
58
int connfd = -1;
 
59
struct termios saved_tc;
 
60
int listenfd=-1;
 
61
int off=0;
 
62
int on=1;
 
63
 
 
64
#define max(a, b) ((a>b) ? a : b)
 
65
 
 
66
static void
 
67
restore_terminal(void)
 
68
{
 
69
        if (tcsetattr(localfd, 0, &saved_tc) == -1)
 
70
           perror("tcsetattr");
 
71
}
 
72
 
 
73
static void
 
74
setup_terminal(void)
 
75
{
 
76
        struct termios tc;
 
77
 
 
78
                if (tcgetattr(0, &tc)==-1)
 
79
                {
 
80
                        perror("tcgetattr");
 
81
                        exit(1);
 
82
                }
 
83
 
 
84
                if (tcgetattr(0, &saved_tc)==-1)
 
85
                {
 
86
                        perror("tcgetattr");
 
87
                        exit(1);
 
88
                }
 
89
 
 
90
                atexit(restore_terminal);
 
91
 
 
92
                tc.c_lflag &= ~(ICANON|ECHO|ISIG);
 
93
                tc.c_cc[VMIN]=1;
 
94
                tc.c_cc[VTIME]=1;
 
95
 
 
96
                if (tcsetattr(0, 0, &tc) == -1)
 
97
                   perror("tcsetattr");
 
98
}
 
99
 
 
100
int
 
101
wait_connect(void)
 
102
{
 
103
        if (listen(listenfd, 1) == -1)
 
104
        {
 
105
                perror("listen");
 
106
                exit(1);
 
107
        }
 
108
 
 
109
        printf("Waiting for a new connection - hit ^C to exit.\n");
 
110
 
 
111
        if ((connfd=accept(listenfd, NULL, NULL))==-1)
 
112
        {
 
113
                perror("accept");
 
114
                exit(1);
 
115
        }
 
116
 
 
117
        printf("Connected\n\n");fflush(stdout);
 
118
 
 
119
        printf("You may need to type ^L after running vi.\n");
 
120
        printf("\n");
 
121
        printf("Hit enter couple of times after exiting the shell so that\n");
 
122
        printf("you can kill the osspartysh program. If the program is left\n");
 
123
        printf("running after a session then new clients can connect the same host/port again.\n");
 
124
        printf("\n");fflush(stdout);
 
125
 
 
126
        setsockopt(connfd, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off));
 
127
 
 
128
        return 1;
 
129
}
 
130
 
 
131
static void
 
132
terminal_loop(int connfd)
 
133
{
 
134
        fd_set readfds;
 
135
        int n, l;
 
136
        char buf[512];
 
137
 
 
138
        while (1)
 
139
        {
 
140
                FD_ZERO(&readfds);
 
141
 
 
142
                FD_SET(0, &readfds);
 
143
                FD_SET(connfd, &readfds);
 
144
 
 
145
                if ((n=select(connfd+1, &readfds, NULL, NULL, NULL))==-1)
 
146
                {
 
147
                        perror("select");
 
148
                        return;
 
149
                }
 
150
 
 
151
                if (FD_ISSET(0, &readfds))
 
152
                {
 
153
                        if ((l=read(0, buf, sizeof(buf)))<0)
 
154
                        {
 
155
                                perror("read(0)");
 
156
                                return;
 
157
                        }
 
158
 
 
159
                        if (write(connfd, buf, l)!=l)
 
160
                        {
 
161
                                perror("write(conn)");
 
162
                                return;
 
163
                        }
 
164
                }
 
165
 
 
166
                if (FD_ISSET(connfd, &readfds))
 
167
                {
 
168
                        if ((l=read(connfd, buf, sizeof(buf)))<0)
 
169
                        {
 
170
                                perror("read(conn)");
 
171
                                exit(0);
 
172
                        }
 
173
 
 
174
                        if (write(1, buf, l)!=l)
 
175
                        {
 
176
                                perror("write(1)");
 
177
                                return;
 
178
                        }
 
179
                }
 
180
        }
 
181
}
 
182
 
 
183
static void
 
184
shell_loop(int connfd, int infd, int outfd)
 
185
{
 
186
        fd_set readfds;
 
187
        int n, l;
 
188
        char buf[512];
 
189
 
 
190
        while (1)
 
191
        {
 
192
                FD_ZERO(&readfds);
 
193
 
 
194
                FD_SET(infd, &readfds);
 
195
                if (infd != 0)
 
196
                   FD_SET(0, &readfds);
 
197
                FD_SET(connfd, &readfds);
 
198
 
 
199
                if ((n=select(max(infd, connfd)+1, &readfds, NULL, NULL, NULL))==-1)
 
200
                {
 
201
                        perror("select");
 
202
                        return;
 
203
                }
 
204
 
 
205
                if (FD_ISSET(infd, &readfds))
 
206
                {
 
207
                        if ((l=read(infd, buf, sizeof(buf)))<0)
 
208
                        {
 
209
                                if (errno == EIO)
 
210
                                {
 
211
                                        printf("Disconnected\n");
 
212
                                        exit(1);
 
213
                                }
 
214
 
 
215
                                perror("read(infd)");
 
216
                                return;
 
217
                        }
 
218
 
 
219
                        if (write(connfd, buf, l)!=l)
 
220
                        {
 
221
                                perror("write(conn)");
 
222
                                return;
 
223
                        }
 
224
 
 
225
                        if (write(1, buf, l)!=l) // Echo to the local terminal
 
226
                           exit(1);
 
227
                }
 
228
 
 
229
                if (FD_ISSET(connfd, &readfds))
 
230
                {
 
231
                        if ((l=read(connfd, buf, sizeof(buf)))<0)
 
232
                        {
 
233
                                perror("read(conn)");
 
234
                                exit(0);
 
235
                        }
 
236
 
 
237
                        if (write(outfd, buf, l)!=l)
 
238
                        {
 
239
                                perror("write(outfd)");
 
240
                                return;
 
241
                        }
 
242
 
 
243
                        // write(1, buf, l); // Echo to the local terminal
 
244
                }
 
245
 
 
246
                if (infd != 0 && FD_ISSET(0, &readfds))
 
247
                {
 
248
                        if ((l=read(0, buf, sizeof(buf)))<0)
 
249
                        {
 
250
                                perror("read(0)");
 
251
                                exit(0);
 
252
                        }
 
253
 
 
254
                        if (write(outfd, buf, l)!=l)
 
255
                        {
 
256
                                perror("write(outfd)");
 
257
                                return;
 
258
                        }
 
259
 
 
260
                        // write(1, buf, l); // Echo to the local terminal
 
261
                }
 
262
        }
 
263
}
 
264
 
 
265
void
 
266
handle_connection(int connfd)
 
267
{
 
268
        char welcomebuf[PARTYSH_HDRSIZE] = {0};
 
269
 
 
270
        sprintf(welcomebuf, PARTYSH_MAGIC " " PARTYSH_VERSION " Just testing");
 
271
        if (write(connfd, welcomebuf, PARTYSH_HDRSIZE) != PARTYSH_HDRSIZE)
 
272
        {
 
273
                perror("send welcome");
 
274
                fprintf(stderr, "Cannot send the welcome string\n");
 
275
                exit(1);
 
276
        }
 
277
 
 
278
        setup_terminal();
 
279
        localfd=dup(0);
 
280
 
 
281
        if (fork())
 
282
           {
 
283
                /* Parent process */
 
284
                close(connfd);
 
285
                wait(NULL);
 
286
                printf("Session closed1\n");fflush(stdout);
 
287
                restore_terminal();
 
288
           }
 
289
        else
 
290
           {
 
291
                terminal_loop(connfd);
 
292
                close(connfd);
 
293
           }
 
294
 
 
295
}
 
296
 
 
297
int
 
298
run_daemon(int port)
 
299
{
 
300
        struct sockaddr_in servaddr;
 
301
 
 
302
        if (port==0)
 
303
        {
 
304
                fprintf(stderr, "Please give a port (-p)\n");
 
305
                exit(1);
 
306
        }
 
307
 
 
308
        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
 
309
        {
 
310
                perror("socket");
 
311
                exit(1);
 
312
        }
 
313
 
 
314
        bzero(&servaddr, sizeof(servaddr));
 
315
        servaddr.sin_family = AF_INET;
 
316
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 
317
        servaddr.sin_port = htons(port);
 
318
 
 
319
        if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr))==-1)
 
320
        {
 
321
                perror("bind");
 
322
                exit(1);
 
323
        }
 
324
 
 
325
        while (1)
 
326
        {
 
327
        
 
328
           if (!wait_connect())
 
329
           {
 
330
              perror("wait connection");
 
331
              exit(1);
 
332
           }
 
333
 
 
334
           handle_connection(connfd);
 
335
        }
 
336
 
 
337
        close(listenfd);
 
338
 
 
339
        return 0;
 
340
}
 
341
 
 
342
void
 
343
pty_session(int connfd)
 
344
{
 
345
        mode_t mode;
 
346
        pid_t pid;
 
347
        int ptyfd, fd;
 
348
        FILE *f;
 
349
        char tmpl[32]="/tmp/osspartyshXXXXXX";
 
350
 
 
351
        mode = umask(077);
 
352
        if ((fd = mkstemp(tmpl)) == -1)
 
353
        {
 
354
                perror("mkstemp");
 
355
                exit(-1);
 
356
        }
 
357
        chmod(tmpl, 0700);
 
358
        umask(mode);
 
359
 
 
360
        if ((f = fdopen(fd, "w")) != NULL)
 
361
        {
 
362
                fprintf(f, "PS1=\"[SHARED]@\\h:\\w $ \"\n");
 
363
                fprintf(f, "export PS1\n");
 
364
                fclose(f);
 
365
        }
 
366
        else close(fd);
 
367
 
 
368
        if ((pid=forkpty(&ptyfd, NULL, NULL, NULL))==-1)
 
369
        {
 
370
                perror("forkpty");
 
371
                exit(1);
 
372
        }
 
373
 
 
374
        if (pid != 0)
 
375
           {
 
376
                setup_terminal();
 
377
                sleep(1);
 
378
                unlink(tmpl);
 
379
                shell_loop(connfd, ptyfd, ptyfd);
 
380
                wait(NULL);
 
381
                restore_terminal();
 
382
           }
 
383
        else
 
384
           {
 
385
                execlp("bash", "bash", "--rcfile", tmpl, NULL);
 
386
           }
 
387
}
 
388
 
 
389
int
 
390
run_client(char *host, int port)
 
391
{
 
392
 
 
393
  struct sockaddr_in sa;
 
394
  struct hostent *he;
 
395
  char *ps1, *p;
 
396
  char welcomebuf[PARTYSH_HDRSIZE];
 
397
 
 
398
  int sockfd, connfd;
 
399
 
 
400
        if (host == NULL)
 
401
        {
 
402
                fprintf(stderr, "Please give a host (-h)\n");
 
403
                exit(1);
 
404
        }
 
405
 
 
406
        if (port==0)
 
407
        {
 
408
                fprintf(stderr, "Please give a port (-p)\n");
 
409
                exit(1);
 
410
        }
 
411
 
 
412
  if ((sockfd = socket (PF_INET, SOCK_STREAM, 0)) == -1)
 
413
    {
 
414
      perror ("socket");
 
415
      return 0;
 
416
    }
 
417
 
 
418
  printf("Looking for the server\n");
 
419
 
 
420
  if ((he = gethostbyname (host)) == NULL)
 
421
    {
 
422
      perror("lookup");
 
423
      fprintf(stderr, "Cannot find the support host\n");
 
424
      return 0;
 
425
    }
 
426
 
 
427
  sa.sin_family = AF_INET;
 
428
  sa.sin_port = htons (port);
 
429
 
 
430
  printf ("Connecting to the support center at %s:%d\n", host, port);
 
431
 
 
432
  memcpy ((void *) &sa.sin_addr, *he->h_addr_list, he->h_length);
 
433
  if ((connfd = connect (sockfd, (void *) &sa, sizeof (sa))) == -1)
 
434
    {
 
435
      perror("connect");
 
436
      fprintf(stderr, "Cannot connect to the support center\n");
 
437
      return 0;
 
438
    }
 
439
 
 
440
    if (read(sockfd, welcomebuf, PARTYSH_HDRSIZE) != PARTYSH_HDRSIZE)
 
441
    {
 
442
        perror("receive welcome");
 
443
        exit(1);
 
444
    }
 
445
 
 
446
    // printf("Welcome %s\n", welcomebuf);
 
447
 
 
448
    if (strncmp(welcomebuf, PARTYSH_MAGIC, strlen(PARTYSH_MAGIC))!=0)
 
449
    {
 
450
        fprintf(stderr, "Didn't receive valid velcome string - abort\n");
 
451
        exit(1);
 
452
    }
 
453
 
 
454
    if ((ps1=getenv("PS1")) != NULL)
 
455
    {
 
456
        p = ps1;
 
457
 
 
458
        while (*p)
 
459
        {
 
460
                if (*p == '#') *p= '$';
 
461
                if (*p == '>') *p= '<';
 
462
                p++;
 
463
        }
 
464
        //printf("PS1='%s'\n", ps1);
 
465
 
 
466
        setenv("PS1", ps1, 1);
 
467
    } else setenv("PS1", "ossremote> ", 1);
 
468
 
 
469
    setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &off, sizeof(off));
 
470
    printf("*** Established connection - You are now sharing this session ***\n\n");fflush(stdout);
 
471
    printf("You may need to type ^L after running vi.\n");
 
472
    printf("\n");
 
473
    fflush(stdout);
 
474
 
 
475
#if 0
 
476
    close(0);
 
477
    dup(sockfd);
 
478
    close(1);
 
479
    dup(sockfd);
 
480
    close(2);
 
481
    dup(sockfd);
 
482
 
 
483
    printf("Now connected to the remote system - Hit ^C to disconnect\n");fflush(stdout);
 
484
 
 
485
    execlp("bash", "bash", "-i", NULL);
 
486
    //execlp("sh", "sh", NULL);
 
487
#else
 
488
#  if 1
 
489
    pty_session(sockfd);
 
490
#  else
 
491
    shell_loop(sockfd, 0, 1);
 
492
#  endif    
 
493
#endif
 
494
    close(sockfd);
 
495
    close(connfd);
 
496
 
 
497
        return 0;
 
498
}
 
499
 
 
500
int main(int argc, char *argv[])
 
501
{
 
502
        int i;
 
503
        int daemon_mode=0;
 
504
        int port=0;
 
505
        char *host=NULL;
 
506
 
 
507
        while ((i = getopt(argc, argv, "dp:h:")) != EOF)
 
508
        switch (i)
 
509
        {
 
510
        case 'd':
 
511
                daemon_mode=1;
 
512
                break;
 
513
 
 
514
        case 'p':
 
515
                port = atoi(optarg);
 
516
                break;
 
517
 
 
518
        case 'h':
 
519
                host=optarg;
 
520
                break;
 
521
        }
 
522
 
 
523
        if (daemon_mode)
 
524
           exit(run_daemon(port));
 
525
 
 
526
        exit(run_client(host, port));
 
527
}