1 /******************************************************************************
2 (c) 2001-2013 Christine Caulfield christine.caulfield@googlemail.com
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 ******************************************************************************/
14
15 #include <sys/types.h>
16 #include <unistd.h>
17 #include <syslog.h>
18 #include <time.h>
19 #include <string.h>
20
21 #include <sstream>
22 #include <list>
23 #include <string>
24 #include <map>
25 #include <queue>
26 #include <iterator>
27
28 #include "lat.h"
29 #include "latcp.h"
30 #include "utils.h"
31 #include "services.h"
32 #include "session.h"
33 #include "localport.h"
34 #include "connection.h"
35 #include "circuit.h"
36 #include "latcpcircuit.h"
37 #include "llogincircuit.h"
38 #include "server.h"
39
40
LLOGINCircuit(int _fd)41 LLOGINCircuit::LLOGINCircuit(int _fd):
42 Circuit(_fd)
43 {
44 }
45
46
~LLOGINCircuit()47 LLOGINCircuit::~LLOGINCircuit()
48 {
49 }
50
do_command()51 bool LLOGINCircuit::do_command()
52 {
53 unsigned char head[3];
54 bool retval = true;
55 int ptr;
56
57 debuglog(("llogin: do_command on fd %d\n", fd));
58
59 // Get the message header (cmd & length)
60 if (read(fd, head, sizeof(head)) != 3)
61 return false; // Bad header
62
63 int len = head[1] * 256 + head[2];
64 unsigned char *cmdbuf = new unsigned char[len];
65
66 // Read the message buffer
67 if (read(fd, cmdbuf, len) != len)
68 {
69 delete[] cmdbuf;
70 return false; // Bad message
71 }
72
73 // Have we completed negotiation?
74 if (head[0] != LATCP_VERSION &&
75 state != RUNNING)
76 {
77 delete[] cmdbuf;
78 return false;
79 }
80
81 debuglog(("llogin: do_command %d\n", head[0]));
82
83 // Do the command
84 switch (head[0])
85 {
86 case LATCP_VERSION:
87 if (strcmp(VERSION, (char*)cmdbuf) == 0)
88 {
89 state = RUNNING; // Versions match
90 send_reply(LATCP_VERSION, VERSION, -1);
91 }
92 else
93 {
94 char error[1024];
95 // Truncate cmdbuf at an arbitrary point to make sure it fits into error[], otherwise it's a
96 // potential security problem. Debian bug #699625
97 if (len > 900)
98 len = 900;
99 cmdbuf[len] = '\0';
100 debuglog(("Connect from invalid llogin version %s\n", cmdbuf));
101 sprintf(error, "llogin version %s does not match latd version " VERSION, cmdbuf);
102 send_reply(LATCP_ERRORMSG, error, -1);
103 retval = false;
104 }
105 break;
106
107 case LATCP_SHOWSERVICE:
108 {
109 int verbose = cmdbuf[0];
110 std::ostringstream st;
111
112 debuglog(("llogin: show_services(verbose=%d)\n", verbose));
113
114 LATServices::Instance()->list_services(verbose?true:false, st);
115 send_reply(LATCP_SHOWSERVICE, st.str().c_str(), (int)st.tellp());
116 // st.freeze(false);
117 }
118 break;
119
120 case LATCP_TERMINALSESSION:
121 {
122 // Close the llogincircuit and pretend to be a PTY
123 // connected to a lloginsession.
124 ptr = 0;
125 bool queued = cmdbuf[ptr++];
126 get_string((unsigned char*)cmdbuf, &ptr, (unsigned char*)service);
127 get_string((unsigned char*)cmdbuf, &ptr, (unsigned char*)node);
128 get_string((unsigned char*)cmdbuf, &ptr, (unsigned char*)port);
129 get_string((unsigned char*)cmdbuf, &ptr, (unsigned char*)localport);
130 get_string((unsigned char*)cmdbuf, &ptr, (unsigned char*)password);
131
132 debuglog(("Terminal session for S:%s, N:%s, P:%s\n",
133 service, node, port));
134
135 // Do the biz
136 if (LATServer::Instance()->make_llogin_connection(fd,
137 service,
138 node,
139 port,
140 localport,
141 password,
142 queued) < 0)
143 {
144 debuglog(("sending failure back to llogin\n"));
145 send_reply(LATCP_ERRORMSG, "Can't find LAT service.", -1);
146 }
147 else
148 {
149 send_reply(LATCP_ACK, "", -1);
150 state = TERMINAL;
151 }
152 }
153 break;
154
155 default:
156 syslog(LOG_INFO, "Unknown llogin command %d\n", head[0]);
157 retval = false;
158 break;
159 }
160
161 delete[] cmdbuf;
162 return retval;
163 }
164