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