Branch data Line data Source code
1 : : // $Id: RSH.cc 6219 2008-10-01 05:39:07Z vern $
2 : :
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include "NetVar.h"
8 : : #include "Event.h"
9 : : #include "RSH.h"
10 : :
11 : :
12 : : // FIXME: this code should probably be merged with Rlogin.cc.
13 : :
14 : : Contents_Rsh_Analyzer::Contents_Rsh_Analyzer(Connection* conn, bool orig,
15 : 0 : Rsh_Analyzer* arg_analyzer)
16 : 0 : : ContentLine_Analyzer(AnalyzerTag::Contents_Rsh, conn, orig)
17 : : {
18 : 0 : num_bytes_to_scan = num_bytes_to_scan = 0;
19 : 0 : analyzer = arg_analyzer;
20 : :
21 [ # # # # ]: 0 : if ( orig )
22 : 0 : state = save_state = RSH_FIRST_NULL;
23 : : else
24 : 0 : state = RSH_LINE_MODE;
25 : 0 : }
26 : :
27 : 0 : Contents_Rsh_Analyzer::~Contents_Rsh_Analyzer()
28 : : {
29 [ # # ][ # # ]: 0 : }
[ # # ]
30 : :
31 : 0 : void Contents_Rsh_Analyzer::DoDeliver(int len, const u_char* data)
32 : : {
33 : 0 : TCP_Analyzer* tcp = static_cast<TCP_ApplicationAnalyzer*>(Parent())->TCP();
34 [ # # ]: 0 : assert(tcp);
35 : :
36 [ # # ]: 0 : int endp_state = IsOrig() ? tcp->OrigState() : tcp->RespState();
37 : :
38 [ # # ]: 0 : for ( ; len > 0; --len, ++data )
39 : : {
40 [ # # ]: 0 : if ( offset >= buf_len )
41 : 0 : InitBuffer(buf_len * 2);
42 : :
43 : 0 : unsigned int c = data[0];
44 : :
45 [ # # # # ]: 0 : switch ( state ) {
46 : : case RSH_FIRST_NULL:
47 [ # # ][ # # ]: 0 : if ( endp_state == TCP_ENDPOINT_PARTIAL ||
48 : : // We can be in closed if the data's due to
49 : : // a dataful FIN being the first thing we see.
50 : : endp_state == TCP_ENDPOINT_CLOSED )
51 : : {
52 : 0 : state = RSH_UNKNOWN;
53 : 0 : ++len, --data; // put back c and reprocess
54 : 0 : continue;
55 : : }
56 : :
57 [ # # ][ # # ]: 0 : if ( c >= '0' && c <= '9' )
58 : : ; // skip stderr port number
59 [ # # ]: 0 : else if ( c == '\0' )
60 : 0 : state = RSH_CLIENT_USER_NAME;
61 : : else
62 : 0 : BadProlog();
63 : :
64 : 0 : break;
65 : :
66 : : case RSH_CLIENT_USER_NAME:
67 : : case RSH_SERVER_USER_NAME:
68 : 0 : buf[offset++] = c;
69 [ # # ]: 0 : if ( c == '\0' )
70 : : {
71 [ # # ]: 0 : if ( state == RSH_CLIENT_USER_NAME )
72 : : {
73 : 0 : analyzer->ClientUserName((const char*) buf);
74 : 0 : state = RSH_SERVER_USER_NAME;
75 : : }
76 : :
77 [ # # ][ # # ]: 0 : else if ( state == RSH_SERVER_USER_NAME &&
78 : : offset > 1 )
79 : : {
80 : 0 : analyzer->ServerUserName((const char*) buf);
81 : 0 : save_state = state;
82 : 0 : state = RSH_LINE_MODE;
83 : : }
84 : :
85 : 0 : offset = 0;
86 : : }
87 : 0 : break;
88 : :
89 : : case RSH_LINE_MODE:
90 : : case RSH_UNKNOWN:
91 : : case RSH_PRESUMED_REJECTED:
92 [ # # ][ # # ]: 0 : if ( state == RSH_LINE_MODE &&
93 : : state == RSH_PRESUMED_REJECTED )
94 : : {
95 : 0 : Conn()->Weird("rsh_text_after_rejected");
96 : 0 : state = RSH_UNKNOWN;
97 : : }
98 : :
99 [ # # ][ # # ]: 0 : if ( c == '\n' || c == '\r' )
100 : : { // CR or LF (RFC 1282)
101 [ # # ][ # # ]: 0 : if ( c == '\n' && last_char == '\r' )
102 : : // Compress CRLF to just 1 termination.
103 : : ;
104 : : else
105 : : {
106 : 0 : buf[offset] = '\0';
107 : 0 : ForwardStream(offset, buf, IsOrig()); \
108 : : save_state = RSH_LINE_MODE;
109 : 0 : offset = 0;
110 : 0 : break;
111 : : }
112 : : }
113 : :
114 [ # # ]: 0 : if ( c == '\0' )
115 : : {
116 : 0 : buf[offset] = '\0';
117 : 0 : ForwardStream(offset, buf, IsOrig()); \
118 : : save_state = RSH_LINE_MODE;
119 : 0 : offset = 0;
120 : 0 : break;
121 : : }
122 : :
123 : : else
124 : 0 : buf[offset++] = c;
125 : :
126 : 0 : last_char = c;
127 : 0 : break;
128 : :
129 : : default:
130 : 0 : internal_error("bad state in Contents_Rsh_Analyzer::DoDeliver");
131 : : break;
132 : : }
133 : : }
134 : 0 : }
135 : :
136 : 0 : void Contents_Rsh_Analyzer::BadProlog()
137 : : {
138 : 0 : Conn()->Weird("bad_rsh_prolog");
139 : 0 : state = RSH_UNKNOWN;
140 : 0 : }
141 : :
142 : 0 : Rsh_Analyzer::Rsh_Analyzer(Connection* conn)
143 : 0 : : Login_Analyzer(AnalyzerTag::Rsh, conn)
144 : : {
145 : 0 : contents_orig = new Contents_Rsh_Analyzer(conn, true, this);
146 : 0 : contents_resp = new Contents_Rsh_Analyzer(conn, false, this);
147 : 0 : AddSupportAnalyzer(contents_orig);
148 : 0 : AddSupportAnalyzer(contents_resp);
149 : 0 : }
150 : :
151 : 0 : void Rsh_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
152 : : {
153 : 0 : Login_Analyzer::DeliverStream(len, data, orig);
154 : :
155 : 0 : const char* line = (const char*) data;
156 : 0 : val_list* vl = new val_list;
157 : :
158 : 0 : line = skip_whitespace(line);
159 : 0 : vl->append(BuildConnVal());
160 [ # # ]: 0 : vl->append(client_name ? client_name->Ref() : new StringVal("<none>"));
161 [ # # ]: 0 : vl->append(username ? username->Ref() : new StringVal("<none>"));
162 : 0 : vl->append(new StringVal(line));
163 : :
164 [ # # # # ]: 0 : if ( orig && rsh_request )
[ # # ]
165 : : {
166 [ # # ]: 0 : if ( contents_orig->RshSaveState() == RSH_SERVER_USER_NAME )
167 : : // First input
168 : 0 : vl->append(new Val(true, TYPE_BOOL));
169 : : else
170 : 0 : vl->append(new Val(false, TYPE_BOOL));
171 : :
172 : 0 : ConnectionEvent(rsh_request, vl);
173 : : }
174 : :
175 [ # # ]: 0 : else if ( rsh_reply )
176 : 0 : ConnectionEvent(rsh_reply, vl);
177 : 0 : }
178 : :
179 : 0 : void Rsh_Analyzer::ClientUserName(const char* s)
180 : : {
181 [ # # ]: 0 : if ( client_name )
182 : 0 : internal_error("multiple rsh client names");
183 : :
184 : 0 : client_name = new StringVal(s);
185 : 0 : }
186 : :
187 : 0 : void Rsh_Analyzer::ServerUserName(const char* s)
188 : : {
189 [ # # ]: 0 : if ( username )
190 : 0 : internal_error("multiple rsh initial client names");
191 : :
192 : 0 : username = new StringVal(s);
193 [ + - ][ + - ]: 6 : }
|