1 | diff --git a/data/Makefile.am b/data/Makefile.am
|
---|
2 | index 0bb621f..44542fa 100644
|
---|
3 | --- a/data/Makefile.am
|
---|
4 | +++ b/data/Makefile.am
|
---|
5 | @@ -1,6 +1,6 @@
|
---|
6 | dist_noinst_DATA = install.nsi.in \
|
---|
7 | makezip.sh.in \
|
---|
8 | - libgcc_s_sjlj-1.dll \
|
---|
9 | + libgcc_s_dw2-1.dll \
|
---|
10 | libstdc++-6.dll \
|
---|
11 | libwinpthread-1.dll \
|
---|
12 | nsis_appid.dll \
|
---|
13 | diff --git a/data/install.nsi.in b/data/install.nsi.in
|
---|
14 | index 529b94e..18f1f0e 100644
|
---|
15 | --- a/data/install.nsi.in
|
---|
16 | +++ b/data/install.nsi.in
|
---|
17 | @@ -874,12 +874,12 @@ Section "FileZilla Client" SecMain
|
---|
18 | ; MinGW runtime libraries
|
---|
19 |
|
---|
20 | ; First get rid of remnants
|
---|
21 | - !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libgcc_s_sjlj-1.dll"
|
---|
22 | + !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libgcc_s_dw2-1.dll"
|
---|
23 | !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libstdc++-6.dll"
|
---|
24 | !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libwinpthread-1.dll"
|
---|
25 |
|
---|
26 | ; Now install new version of runtime
|
---|
27 | - !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "${srcdir}\libgcc_s_sjlj-1.dll" "$INSTDIR\libgcc_s_sjlj-1.dll" "$INSTDIR"
|
---|
28 | + !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "${srcdir}\libgcc_s_dw2-1.dll" "$INSTDIR\libgcc_s_dw2-1.dll" "$INSTDIR"
|
---|
29 | !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "${srcdir}\libstdc++-6.dll" "$INSTDIR\libstdc++-6.dll" "$INSTDIR"
|
---|
30 | !insertmacro InstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "${srcdir}\libwinpthread-1.dll" "$INSTDIR\libwinpthread-1.dll" "$INSTDIR"
|
---|
31 |
|
---|
32 | @@ -1300,7 +1300,7 @@ Section "Uninstall"
|
---|
33 | Delete "$INSTDIR\fzputtygen.exe"
|
---|
34 |
|
---|
35 | ; MinGW runtime libraries
|
---|
36 | - !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libgcc_s_sjlj-1.dll"
|
---|
37 | + !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libgcc_s_dw2-1.dll"
|
---|
38 | !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libstdc++-6.dll"
|
---|
39 | !insertmacro UnInstallLib DLL NOTSHARED REBOOT_NOTPROTECTED "$INSTDIR\libwinpthread-1.dll"
|
---|
40 |
|
---|
41 | diff --git a/data/libgcc_s_dw2-1.dll b/data/libgcc_s_dw2-1.dll
|
---|
42 | new file mode 100644
|
---|
43 | index 0000000..3ac46a5
|
---|
44 | Binary files /dev/null and b/data/libgcc_s_dw2-1.dll differ
|
---|
45 | diff --git a/data/libstdc++-6.dll b/data/libstdc++-6.dll
|
---|
46 | index c4804b8..b0fd5e4 100644
|
---|
47 | Binary files a/data/libstdc++-6.dll and b/data/libstdc++-6.dll differ
|
---|
48 | diff --git a/data/libwinpthread-1.dll b/data/libwinpthread-1.dll
|
---|
49 | index ac09bcc..511c25c 100644
|
---|
50 | Binary files a/data/libwinpthread-1.dll and b/data/libwinpthread-1.dll differ
|
---|
51 | diff --git a/data/makezip.sh.in b/data/makezip.sh.in
|
---|
52 | index 96bb1cd..46f4859 100644
|
---|
53 | --- a/data/makezip.sh.in
|
---|
54 | +++ b/data/makezip.sh.in
|
---|
55 | @@ -54,7 +54,7 @@ copy_libtool "src/putty" "fzputtygen.exe"
|
---|
56 | copy_libtool "src/fzshellext" "libfzshellext-0.dll" "fzshellext.dll"
|
---|
57 |
|
---|
58 | cp "$top_srcdir/src/fzshellext/fzshellext_64.dll" "$targetdir/fzshellext_64.dll" || exit 1
|
---|
59 | -cp "$top_srcdir/data/libgcc_s_sjlj-1.dll" "$targetdir/libgcc_s_sjlj-1.dll" || exit 1
|
---|
60 | +cp "$top_srcdir/data/libgcc_s_dw2-1.dll" "$targetdir/libgcc_s_dw2-1.dll" || exit 1
|
---|
61 | cp "$top_srcdir/data/libstdc++-6.dll" "$targetdir/libstdc++-6.dll" || exit 1
|
---|
62 | cp "$top_srcdir/data/libwinpthread-1.dll" "$targetdir/libwinpthread-1.dll" || exit 1
|
---|
63 |
|
---|
64 | diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am
|
---|
65 | index a13bf4b..61208a8 100644
|
---|
66 | --- a/src/engine/Makefile.am
|
---|
67 | +++ b/src/engine/Makefile.am
|
---|
68 | @@ -20,6 +20,8 @@ libengine_a_SOURCES = \
|
---|
69 | FileZillaEngine.cpp \
|
---|
70 | file.cpp \
|
---|
71 | ftpcontrolsocket.cpp \
|
---|
72 | + gssinterface.cpp \
|
---|
73 | + gsssocket.cpp \
|
---|
74 | httpcontrolsocket.cpp \
|
---|
75 | iothread.cpp \
|
---|
76 | local_filesys.cpp \
|
---|
77 | @@ -52,6 +54,7 @@ noinst_HEADERS = backend.h \
|
---|
78 | filezilla.h \
|
---|
79 | file.h \
|
---|
80 | ftpcontrolsocket.h \
|
---|
81 | + gsssocket.h \
|
---|
82 | httpcontrolsocket.h iothread.h \
|
---|
83 | logging_private.h \
|
---|
84 | pathcache.h \
|
---|
85 | diff --git a/src/engine/ftpcontrolsocket.cpp b/src/engine/ftpcontrolsocket.cpp
|
---|
86 | index 5d2c0ff..a92be07 100644
|
---|
87 | --- a/src/engine/ftpcontrolsocket.cpp
|
---|
88 | +++ b/src/engine/ftpcontrolsocket.cpp
|
---|
89 | @@ -13,6 +13,7 @@
|
---|
90 | #include "transfersocket.h"
|
---|
91 | #include "local_filesys.h"
|
---|
92 | #include "proxy.h"
|
---|
93 | +#include "gssinterface.h"
|
---|
94 |
|
---|
95 | #include <wx/filename.h>
|
---|
96 | #include <wx/log.h>
|
---|
97 | @@ -22,19 +23,21 @@
|
---|
98 | #include <algorithm>
|
---|
99 |
|
---|
100 | #define LOGON_WELCOME 0
|
---|
101 | -#define LOGON_AUTH_TLS 1
|
---|
102 | -#define LOGON_AUTH_SSL 2
|
---|
103 | -#define LOGON_AUTH_WAIT 3
|
---|
104 | -#define LOGON_LOGON 4
|
---|
105 | -#define LOGON_SYST 5
|
---|
106 | -#define LOGON_FEAT 6
|
---|
107 | -#define LOGON_CLNT 7
|
---|
108 | -#define LOGON_OPTSUTF8 8
|
---|
109 | -#define LOGON_PBSZ 9
|
---|
110 | -#define LOGON_PROT 10
|
---|
111 | -#define LOGON_OPTSMLST 11
|
---|
112 | -#define LOGON_CUSTOMCOMMANDS 12
|
---|
113 | -#define LOGON_DONE 13
|
---|
114 | +#define LOGON_AUTH_GSS 1
|
---|
115 | +#define LOGON_AUTH_ADAT 2
|
---|
116 | +#define LOGON_AUTH_TLS 3
|
---|
117 | +#define LOGON_AUTH_SSL 4
|
---|
118 | +#define LOGON_AUTH_WAIT 5
|
---|
119 | +#define LOGON_LOGON 6
|
---|
120 | +#define LOGON_SYST 7
|
---|
121 | +#define LOGON_FEAT 8
|
---|
122 | +#define LOGON_CLNT 9
|
---|
123 | +#define LOGON_OPTSUTF8 10
|
---|
124 | +#define LOGON_PBSZ 11
|
---|
125 | +#define LOGON_PROT 12
|
---|
126 | +#define LOGON_OPTSMLST 13
|
---|
127 | +#define LOGON_CUSTOMCOMMANDS 14
|
---|
128 | +#define LOGON_DONE 15
|
---|
129 |
|
---|
130 | CRawTransferOpData::CRawTransferOpData()
|
---|
131 | : COpData(Command::rawtransfer)
|
---|
132 | @@ -118,22 +121,31 @@ struct t_loginCommand
|
---|
133 | class CFtpLogonOpData : public CConnectOpData
|
---|
134 | {
|
---|
135 | public:
|
---|
136 | - CFtpLogonOpData()
|
---|
137 | + CFtpLogonOpData(CControlSocket *pSocket)
|
---|
138 | {
|
---|
139 | waitChallenge = false;
|
---|
140 | gotPassword = false;
|
---|
141 | waitForAsyncRequest = false;
|
---|
142 | gotFirstWelcomeLine = false;
|
---|
143 | ftp_proxy_type = 0;
|
---|
144 | + pControlSocket = pSocket;
|
---|
145 |
|
---|
146 | customCommandIndex = 0;
|
---|
147 |
|
---|
148 | for (int i = 0; i < LOGON_DONE; ++i)
|
---|
149 | neededCommands[i] = 1;
|
---|
150 | +
|
---|
151 | + if (!IsGssLoaded())
|
---|
152 | + neededCommands[LOGON_AUTH_GSS] = 0;
|
---|
153 | +
|
---|
154 | + neededCommands[LOGON_AUTH_ADAT] = 0;
|
---|
155 | }
|
---|
156 |
|
---|
157 | virtual ~CFtpLogonOpData()
|
---|
158 | +
|
---|
159 | {
|
---|
160 | + if (target_name)
|
---|
161 | + GssReleaseName(pControlSocket, (void **) &target_name);
|
---|
162 | }
|
---|
163 |
|
---|
164 | wxString challenge; // Used for interactive logons
|
---|
165 | @@ -149,6 +161,11 @@ public:
|
---|
166 | std::list<t_loginCommand> loginSequence;
|
---|
167 |
|
---|
168 | int ftp_proxy_type;
|
---|
169 | +
|
---|
170 | + CControlSocket *pControlSocket;
|
---|
171 | + wxString adatSend;
|
---|
172 | + void *target_name = NULL;
|
---|
173 | + int lastcode = -1;
|
---|
174 | };
|
---|
175 |
|
---|
176 | class CFtpDeleteOpData : public COpData
|
---|
177 | @@ -189,7 +206,9 @@ CFtpControlSocket::CFtpControlSocket(CFileZillaEnginePrivate & engine)
|
---|
178 | m_pendingReplies = 1;
|
---|
179 | m_pTlsSocket = 0;
|
---|
180 | m_protectDataChannel = false;
|
---|
181 | + m_protectCommandChannel = false;
|
---|
182 | m_lastTypeBinary = -1;
|
---|
183 | + m_protBufferSize = 0;
|
---|
184 |
|
---|
185 | // Enable TCP_NODELAY, speeds things up a bit.
|
---|
186 | // Enable SO_KEEPALIVE, lots of clueless users have broken routers and
|
---|
187 | @@ -406,6 +425,11 @@ void CFtpControlSocket::ParseResponse()
|
---|
188 | return;
|
---|
189 | }
|
---|
190 |
|
---|
191 | + if (m_Response[0] == '6' && m_protectCommandChannel) {
|
---|
192 | + DecryptResponse();
|
---|
193 | + return;
|
---|
194 | + }
|
---|
195 | +
|
---|
196 | if (m_Response[0] != '1') {
|
---|
197 | if (m_pendingReplies > 0)
|
---|
198 | m_pendingReplies--;
|
---|
199 | @@ -719,6 +743,58 @@ int CFtpControlSocket::LogonParseResponse()
|
---|
200 | return FZ_REPLY_DISCONNECTED;
|
---|
201 | }
|
---|
202 | }
|
---|
203 | + else if (pData->opState == LOGON_AUTH_GSS)
|
---|
204 | + {
|
---|
205 | + if (code == 3) {
|
---|
206 | + pData->neededCommands[LOGON_AUTH_ADAT] = 1;
|
---|
207 | + pData->neededCommands[LOGON_AUTH_TLS] = 0;
|
---|
208 | + pData->neededCommands[LOGON_AUTH_SSL] = 0;
|
---|
209 | + pData->neededCommands[LOGON_AUTH_WAIT] = 0;
|
---|
210 | + pData->neededCommands[LOGON_PBSZ] = 1;
|
---|
211 | + pData->neededCommands[LOGON_PROT] = 1;
|
---|
212 | + m_protBufferSize =
|
---|
213 | + engine_.GetOptions().GetOptionVal(OPTION_GSS_PROTBUFSIZE);
|
---|
214 | + }
|
---|
215 | + }
|
---|
216 | + else if (pData->opState == LOGON_AUTH_ADAT)
|
---|
217 | + {
|
---|
218 | + if (code == 2 || code == 3) {
|
---|
219 | + /*
|
---|
220 | + * Scan this response to see if we got an ADAT
|
---|
221 | + * message. If we did, decode the data and
|
---|
222 | + * save it.
|
---|
223 | + */
|
---|
224 | +
|
---|
225 | + int pos = m_Response.Find(_T("ADAT="));
|
---|
226 | +
|
---|
227 | + pData->lastcode = code;
|
---|
228 | +
|
---|
229 | + if (pos != wxNOT_FOUND) {
|
---|
230 | + wxString data = m_Response.Mid(pos + 5);
|
---|
231 | + bool more;
|
---|
232 | +
|
---|
233 | + if (!ProcessAdatResponse(data, &more)) {
|
---|
234 | + LogMessage(MessageType::Status,
|
---|
235 | + _("Processing of ADAT response failed"));
|
---|
236 | + DoClose(FZ_REPLY_INTERNALERROR);
|
---|
237 | + return FZ_REPLY_ERROR;
|
---|
238 | + }
|
---|
239 | + /*
|
---|
240 | + * If we have a token to send, bump our
|
---|
241 | + * opState back so we can send it.
|
---|
242 | + */
|
---|
243 | +
|
---|
244 | + if (more)
|
---|
245 | + pData->opState--;
|
---|
246 | +
|
---|
247 | + }
|
---|
248 | + } else {
|
---|
249 | + /* Any other response is an error */
|
---|
250 | + LogMessage(MessageType::Status, _("Invalid response to ADAT"));
|
---|
251 | + DoClose(FZ_REPLY_INTERNALERROR);
|
---|
252 | + return FZ_REPLY_ERROR;
|
---|
253 | + }
|
---|
254 | + }
|
---|
255 | else if (pData->opState == LOGON_AUTH_TLS ||
|
---|
256 | pData->opState == LOGON_AUTH_SSL)
|
---|
257 | {
|
---|
258 | @@ -893,10 +969,39 @@ int CFtpControlSocket::LogonParseResponse()
|
---|
259 | m_useUTF8 = false;
|
---|
260 | }
|
---|
261 | }
|
---|
262 | - else if (pData->opState == LOGON_PROT) {
|
---|
263 | - if (code == 2 || code == 3)
|
---|
264 | + else if (pData->opState == LOGON_PROT)
|
---|
265 | + {
|
---|
266 | + if (m_protectDataChannel && code != 2)
|
---|
267 | + m_protectDataChannel = false;
|
---|
268 | + else if (code == 2 || code == 3)
|
---|
269 | m_protectDataChannel = true;
|
---|
270 | }
|
---|
271 | + else if (pData->opState == LOGON_PBSZ)
|
---|
272 | + {
|
---|
273 | + if (code != 2)
|
---|
274 | + m_protectDataChannel = false;
|
---|
275 | +
|
---|
276 | + if (m_protectDataChannel) {
|
---|
277 | + /*
|
---|
278 | + * Parse the PBSZ response to see if the buffer size
|
---|
279 | + * has been specified.
|
---|
280 | + */
|
---|
281 | +
|
---|
282 | + int pos = m_Response.Find(_T("PBSZ="));
|
---|
283 | +
|
---|
284 | + if (pos != wxNOT_FOUND) {
|
---|
285 | + wxString data = m_Response.Mid(pos + 5);
|
---|
286 | + unsigned long retbufsz;
|
---|
287 | +
|
---|
288 | + if (! data.ToCULong(&retbufsz)) {
|
---|
289 | + LogMessage(MessageType::Status, _("Invalid PBSZ response, ignoring."));
|
---|
290 | + } else {
|
---|
291 | + if (retbufsz < m_protBufferSize)
|
---|
292 | + m_protBufferSize = retbufsz;
|
---|
293 | + }
|
---|
294 | + }
|
---|
295 | + }
|
---|
296 | + }
|
---|
297 | else if (pData->opState == LOGON_CUSTOMCOMMANDS) {
|
---|
298 | ++pData->customCommandIndex;
|
---|
299 | if (pData->customCommandIndex < m_pCurrentServer->GetPostLoginCommands().size())
|
---|
300 | @@ -1053,6 +1158,12 @@ int CFtpControlSocket::LogonSend()
|
---|
301 | res = FZ_REPLY_WOULDBLOCK;
|
---|
302 | LogMessage(MessageType::Debug_Info, _T("LogonSend() called during LOGON_AUTH_WAIT, ignoring"));
|
---|
303 | break;
|
---|
304 | + case LOGON_AUTH_GSS:
|
---|
305 | + res = SendCommand(_T("AUTH GSSAPI"), false, false);
|
---|
306 | + break;
|
---|
307 | + case LOGON_AUTH_ADAT:
|
---|
308 | + res = SendGssAdat();
|
---|
309 | + break;
|
---|
310 | case LOGON_AUTH_TLS:
|
---|
311 | res = SendCommand(_T("AUTH TLS"), false, false);
|
---|
312 | break;
|
---|
313 | @@ -1139,10 +1250,20 @@ int CFtpControlSocket::LogonSend()
|
---|
314 | res = SendCommand(_T("OPTS UTF8 ON"));
|
---|
315 | break;
|
---|
316 | case LOGON_PBSZ:
|
---|
317 | - res = SendCommand(_T("PBSZ 0"));
|
---|
318 | + if (IsGssLoaded() &&
|
---|
319 | + engine_.GetOptions().GetOptionVal(OPTION_GSS_ENCRYPTDATACHAN)) {
|
---|
320 | + m_protectDataChannel = true;
|
---|
321 | + res = SendCommand(_T("PBSZ ") +
|
---|
322 | + std::to_string(m_protBufferSize));
|
---|
323 | + }
|
---|
324 | + else
|
---|
325 | + res = SendCommand(_T("PBSZ 0"));
|
---|
326 | break;
|
---|
327 | case LOGON_PROT:
|
---|
328 | - res = SendCommand(_T("PROT P"));
|
---|
329 | + if (m_protectDataChannel)
|
---|
330 | + res = SendCommand(_T("PROT P"));
|
---|
331 | + else
|
---|
332 | + res = SendCommand(_T("PROT C"));
|
---|
333 | break;
|
---|
334 | case LOGON_CUSTOMCOMMANDS:
|
---|
335 | if (pData->customCommandIndex >= m_pCurrentServer->GetPostLoginCommands().size())
|
---|
336 | @@ -1183,9 +1304,28 @@ int CFtpControlSocket::GetReplyCode() const
|
---|
337 | }
|
---|
338 | }
|
---|
339 |
|
---|
340 | +int CFtpControlSocket::GetFullReplyCode() const
|
---|
341 | +{
|
---|
342 | + unsigned long ret;
|
---|
343 | +
|
---|
344 | + if (m_Response.empty()) {
|
---|
345 | + return 0;
|
---|
346 | + }
|
---|
347 | +
|
---|
348 | + wxString substr = m_Response.Mid(0, 3);
|
---|
349 | +
|
---|
350 | + if (! substr.ToULong(&ret)) {
|
---|
351 | + return 0;
|
---|
352 | + }
|
---|
353 | +
|
---|
354 | + return ret;
|
---|
355 | +}
|
---|
356 | +
|
---|
357 | bool CFtpControlSocket::SendCommand(wxString const& str, bool maskArgs, bool measureRTT)
|
---|
358 | {
|
---|
359 | int pos;
|
---|
360 | + wxCharBuffer buffer;
|
---|
361 | +
|
---|
362 | if (maskArgs && (pos = str.Find(_T(" "))) != -1)
|
---|
363 | {
|
---|
364 | wxString stars('*', str.Length() - pos - 1);
|
---|
365 | @@ -1194,12 +1334,23 @@ bool CFtpControlSocket::SendCommand(wxString const& str, bool maskArgs, bool mea
|
---|
366 | else
|
---|
367 | LogMessageRaw(MessageType::Command, str);
|
---|
368 |
|
---|
369 | - wxCharBuffer buffer = ConvToServer(str + _T("\r\n"));
|
---|
370 | - if (!buffer)
|
---|
371 | + if (m_protectCommandChannel)
|
---|
372 | {
|
---|
373 | - LogMessage(MessageType::Error, _T("Failed to convert command to 8 bit charset"));
|
---|
374 | - return false;
|
---|
375 | + buffer = ProtectCommand(str);
|
---|
376 | + if (!buffer)
|
---|
377 | + {
|
---|
378 | + LogMessage(MessageType::Error, _T("Failed to encrypt command"));
|
---|
379 | + return false;
|
---|
380 | + }
|
---|
381 | + } else {
|
---|
382 | + buffer = ConvToServer(str + _T("\r\n"));
|
---|
383 | + if (!buffer)
|
---|
384 | + {
|
---|
385 | + LogMessage(MessageType::Error, _T("Failed to convert command to 8 bit charset"));
|
---|
386 | + return false;
|
---|
387 | + }
|
---|
388 | }
|
---|
389 | +
|
---|
390 | unsigned int len = (unsigned int)strlen(buffer);
|
---|
391 | bool res = CRealControlSocket::Send(buffer, len);
|
---|
392 | if (res)
|
---|
393 | @@ -4275,7 +4426,7 @@ int CFtpControlSocket::Connect(const CServer &server)
|
---|
394 | delete m_pCurOpData;
|
---|
395 | }
|
---|
396 |
|
---|
397 | - CFtpLogonOpData* pData = new CFtpLogonOpData;
|
---|
398 | + CFtpLogonOpData* pData = new CFtpLogonOpData(this);
|
---|
399 | m_pCurOpData = pData;
|
---|
400 |
|
---|
401 | // Do not use FTP proxy if generic proxy is set
|
---|
402 | @@ -4472,6 +4623,176 @@ int CFtpControlSocket::ParseSubcommandResult(int prevResult)
|
---|
403 | return FZ_REPLY_ERROR;
|
---|
404 | }
|
---|
405 |
|
---|
406 | +int CFtpControlSocket::SendGssAdat()
|
---|
407 | +{
|
---|
408 | + CFtpLogonOpData *pData = reinterpret_cast<CFtpLogonOpData *>(m_pCurOpData);
|
---|
409 | + wxString output_token;
|
---|
410 | + bool complete;
|
---|
411 | +
|
---|
412 | + //
|
---|
413 | + // If data is left over from a init_sec_context call send it now
|
---|
414 | + //
|
---|
415 | +
|
---|
416 | + if (pData->adatSend.length() > 0) {
|
---|
417 | + int ret = SendCommand("ADAT " + pData->adatSend, false, false);
|
---|
418 | + pData->adatSend.Clear();
|
---|
419 | + return ret;
|
---|
420 | + }
|
---|
421 | +
|
---|
422 | + //
|
---|
423 | + // The code here should only be invoked the first time around
|
---|
424 | + //
|
---|
425 | +
|
---|
426 | + if (! pData->target_name) {
|
---|
427 | + wxString target = "host@" + pData->host;
|
---|
428 | + if (!GssImportName(this, target, &pData->target_name))
|
---|
429 | + return false;
|
---|
430 | + }
|
---|
431 | +
|
---|
432 | + if (!GssInitSecContext(this, &gcontext, pData->target_name, true,
|
---|
433 | + wxEmptyString, &output_token, &complete))
|
---|
434 | + return false;
|
---|
435 | +
|
---|
436 | + if (output_token.Length() > 0) {
|
---|
437 | + if (!SendCommand(_T("ADAT ") + output_token, false, false))
|
---|
438 | + return false;
|
---|
439 | + }
|
---|
440 | +
|
---|
441 | + /*
|
---|
442 | + * If lastcode is set, it should be either 2 (complete) or 3
|
---|
443 | + * (more exchanges needed). If it's 2, we should be done
|
---|
444 | + * (GSS_S_COMPLETE).
|
---|
445 | + */
|
---|
446 | +
|
---|
447 | + if (pData->lastcode == 2) {
|
---|
448 | + if (complete) {
|
---|
449 | + LogMessage(MessageType::Status, _("GSSAPI Authentication successful"));
|
---|
450 | + m_protectCommandChannel = true;
|
---|
451 | + } else {
|
---|
452 | + return false;
|
---|
453 | + }
|
---|
454 | + }
|
---|
455 | +
|
---|
456 | + return true;
|
---|
457 | +}
|
---|
458 | +
|
---|
459 | +bool CFtpControlSocket::ProcessAdatResponse(wxString recvdata,
|
---|
460 | + bool *more)
|
---|
461 | +{
|
---|
462 | + CFtpLogonOpData *pData = reinterpret_cast<CFtpLogonOpData *>(m_pCurOpData);
|
---|
463 | + bool complete;
|
---|
464 | +
|
---|
465 | + if (!GssInitSecContext(this, &gcontext, pData->target_name, true,
|
---|
466 | + recvdata, &pData->adatSend, &complete)) {
|
---|
467 | + return false;
|
---|
468 | + }
|
---|
469 | +
|
---|
470 | + if (pData->adatSend.Length() > 0) {
|
---|
471 | + *more = true;
|
---|
472 | + } else {
|
---|
473 | + *more = false;
|
---|
474 | + }
|
---|
475 | +
|
---|
476 | + /*
|
---|
477 | + * If we're done, mark it.
|
---|
478 | + */
|
---|
479 | +
|
---|
480 | + if (pData->lastcode == 2 && complete) {
|
---|
481 | + LogMessage(MessageType::Status, _("GSSAPI Authentication successful"));
|
---|
482 | + m_protectCommandChannel = true;
|
---|
483 | + }
|
---|
484 | +
|
---|
485 | + return true;
|
---|
486 | +}
|
---|
487 | +
|
---|
488 | +wxCharBuffer CFtpControlSocket::ProtectCommand(wxString const& str)
|
---|
489 | +{
|
---|
490 | + wxCharBuffer input = ConvToServer(str);
|
---|
491 | + wxString output;
|
---|
492 | +
|
---|
493 | + if (!GssWrap(this, gcontext, true, input, &output))
|
---|
494 | + {
|
---|
495 | + return wxCharBuffer();
|
---|
496 | + }
|
---|
497 | +
|
---|
498 | + wxString retstr = _("ENC ") + output + _("\r\n");
|
---|
499 | +
|
---|
500 | + return retstr.c_str();
|
---|
501 | +}
|
---|
502 | +
|
---|
503 | +void CFtpControlSocket::DecryptResponse()
|
---|
504 | +{
|
---|
505 | + int code = GetFullReplyCode();
|
---|
506 | + wxString enc_response;
|
---|
507 | + bool encrypted;
|
---|
508 | + wxMemoryBuffer output;
|
---|
509 | +
|
---|
510 | + if (code != 631 && code != 632 && code != 633)
|
---|
511 | + {
|
---|
512 | + LogMessage(MessageType::Error, _T("Unknown response code %d"), code);
|
---|
513 | + return;
|
---|
514 | + }
|
---|
515 | +
|
---|
516 | + bool protect = (code != 631);
|
---|
517 | +
|
---|
518 | + std::list<wxString>::iterator iter = m_MultilineResponseLines.begin();
|
---|
519 | +
|
---|
520 | + while (iter != m_MultilineResponseLines.end())
|
---|
521 | + {
|
---|
522 | + enc_response.Append(iter->Mid(4));
|
---|
523 | + iter++;
|
---|
524 | + }
|
---|
525 | +
|
---|
526 | + enc_response.Append(m_Response.Mid(4));
|
---|
527 | +
|
---|
528 | + if (!GssUnwrap(this, gcontext, enc_response, &output, &encrypted))
|
---|
529 | + return;
|
---|
530 | +
|
---|
531 | + if (protect != encrypted)
|
---|
532 | + {
|
---|
533 | + LogMessage(MessageType::Error, _("Response code did not match encryption level!"));
|
---|
534 | + return;
|
---|
535 | + }
|
---|
536 | + /*
|
---|
537 | + * Because of the way multiline reponses are dealt with in
|
---|
538 | + * GSSAPI, we need to replicate part of OnReceive() here (but
|
---|
539 | + * it's been adapted).
|
---|
540 | + */
|
---|
541 | +
|
---|
542 | + char *start, *bufstart;
|
---|
543 | + start = bufstart = (char *) malloc(output.GetDataLen() + 1);
|
---|
544 | + memcpy(bufstart, output.GetData(), output.GetDataLen());
|
---|
545 | + bufstart[output.GetDataLen()] = '\0';
|
---|
546 | +
|
---|
547 | + for (int i = start - bufstart; i < output.GetDataLen() + 1; ++i)
|
---|
548 | + {
|
---|
549 | + char& p = bufstart[i];
|
---|
550 | + if (p == '\r' ||
|
---|
551 | + p == '\n' ||
|
---|
552 | + p == 0)
|
---|
553 | + {
|
---|
554 | + int len = i - (start - bufstart);
|
---|
555 | + if (!len)
|
---|
556 | + {
|
---|
557 | + ++start;
|
---|
558 | + continue;
|
---|
559 | + }
|
---|
560 | +
|
---|
561 | + p = 0;
|
---|
562 | + wxString line = ConvToLocal(start, i + 1 - (start - bufstart));
|
---|
563 | + start = bufstart + i + 1;
|
---|
564 | +
|
---|
565 | + ParseLine(line);
|
---|
566 | +
|
---|
567 | + // Abort if connection got closed
|
---|
568 | + if (!m_pCurrentServer)
|
---|
569 | + break;
|
---|
570 | + }
|
---|
571 | + }
|
---|
572 | +
|
---|
573 | + free(bufstart);
|
---|
574 | +}
|
---|
575 | +
|
---|
576 | void CFtpControlSocket::operator()(CEventBase const& ev)
|
---|
577 | {
|
---|
578 | if (Dispatch<CTimerEvent>(ev, this, &CFtpControlSocket::OnTimer)) {
|
---|
579 | diff --git a/src/engine/ftpcontrolsocket.h b/src/engine/ftpcontrolsocket.h
|
---|
580 | index a1db93c..de7a2d0 100644
|
---|
581 | --- a/src/engine/ftpcontrolsocket.h
|
---|
582 | +++ b/src/engine/ftpcontrolsocket.h
|
---|
583 | @@ -96,11 +96,18 @@ protected:
|
---|
584 | virtual int ParseSubcommandResult(int prevResult);
|
---|
585 |
|
---|
586 | int GetReplyCode() const;
|
---|
587 | + int GetFullReplyCode() const;
|
---|
588 |
|
---|
589 | int Logon();
|
---|
590 | int LogonParseResponse();
|
---|
591 | int LogonSend();
|
---|
592 |
|
---|
593 | + int SendGssAdat();
|
---|
594 | + bool ProcessAdatResponse(wxString recvdata, bool *more);
|
---|
595 | + void ReportGssError(uint32_t major, uint32_t minor);
|
---|
596 | + wxCharBuffer ProtectCommand(wxString const& str);
|
---|
597 | + void DecryptResponse();
|
---|
598 | +
|
---|
599 | wxString GetPassiveCommand(CRawTransferOpData& data);
|
---|
600 | bool ParsePasvResponse(CRawTransferOpData* pData);
|
---|
601 | bool ParseEpsvResponse(CRawTransferOpData* pData);
|
---|
602 | @@ -139,6 +146,13 @@ protected:
|
---|
603 |
|
---|
604 | CTlsSocket* m_pTlsSocket;
|
---|
605 | bool m_protectDataChannel;
|
---|
606 | + bool m_protectCommandChannel;
|
---|
607 | +
|
---|
608 | + // Context structure for GSSAPI
|
---|
609 | + void *gcontext = NULL;
|
---|
610 | +
|
---|
611 | + // Protection buffer size
|
---|
612 | + int m_protBufferSize;
|
---|
613 |
|
---|
614 | int m_lastTypeBinary;
|
---|
615 |
|
---|
616 | diff --git a/src/engine/gssinterface.cpp b/src/engine/gssinterface.cpp
|
---|
617 | new file mode 100644
|
---|
618 | index 0000000..1af0fb2
|
---|
619 | --- /dev/null
|
---|
620 | +++ b/src/engine/gssinterface.cpp
|
---|
621 | @@ -0,0 +1,982 @@
|
---|
622 | +#include <filezilla.h>
|
---|
623 | +#include "ControlSocket.h"
|
---|
624 | +#include "../interface/Options.h"
|
---|
625 | +
|
---|
626 | +#include <wx/dynlib.h>
|
---|
627 | +#include <wx/base64.h>
|
---|
628 | +#include <wx/filename.h>
|
---|
629 | +
|
---|
630 | +#include "gssinterface.h"
|
---|
631 | +
|
---|
632 | +/*
|
---|
633 | + * We include the generic header file here from the GSSAPI RFC, so we
|
---|
634 | + * don't need to depend on it (but only some of it).
|
---|
635 | + */
|
---|
636 | +
|
---|
637 | +/* -*- mode: c; indent-tabs-mode: nil -*- */
|
---|
638 | +/*
|
---|
639 | + * Copyright 1993 by OpenVision Technologies, Inc.
|
---|
640 | + *
|
---|
641 | + * Permission to use, copy, modify, distribute, and sell this software
|
---|
642 | + * and its documentation for any purpose is hereby granted without fee,
|
---|
643 | + * provided that the above copyright notice appears in all copies and
|
---|
644 | + * that both that copyright notice and this permission notice appear in
|
---|
645 | + * supporting documentation, and that the name of OpenVision not be used
|
---|
646 | + * in advertising or publicity pertaining to distribution of the software
|
---|
647 | + * without specific, written prior permission. OpenVision makes no
|
---|
648 | + * representations about the suitability of this software for any
|
---|
649 | + * purpose. It is provided "as is" without express or implied warranty.
|
---|
650 | + *
|
---|
651 | + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
---|
652 | + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
---|
653 | + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
---|
654 | + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
---|
655 | + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
---|
656 | + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
---|
657 | + * PERFORMANCE OF THIS SOFTWARE.
|
---|
658 | + */
|
---|
659 | +
|
---|
660 | +/*
|
---|
661 | + * Determine platform-dependent configuration.
|
---|
662 | + */
|
---|
663 | +
|
---|
664 | +#if defined(__MACH__) && defined(__APPLE__)
|
---|
665 | +# include <TargetConditionals.h>
|
---|
666 | +# if TARGET_RT_MAC_CFM
|
---|
667 | +# error "Use KfM 4.0 SDK headers for CFM compilation."
|
---|
668 | +# endif
|
---|
669 | +#endif
|
---|
670 | +
|
---|
671 | +#ifndef __has_extension
|
---|
672 | +#define __has_extension(x) 0
|
---|
673 | +#endif
|
---|
674 | +
|
---|
675 | +#ifndef GSSKRB_APPLE_DEPRECATED
|
---|
676 | +#if __has_extension(attribute_deprecated_with_message)
|
---|
677 | +#define GSSKRB_APPLE_DEPRECATED(x) __attribute__((deprecated(x)))
|
---|
678 | +#else
|
---|
679 | +#if !defined(__GNUC__) && !defined(__attribute__)
|
---|
680 | +#define __attribute__(x)
|
---|
681 | +#endif
|
---|
682 | +#define GSSKRB_APPLE_DEPRECATED(x) __attribute__((deprecated))
|
---|
683 | +#endif
|
---|
684 | +#endif
|
---|
685 | +
|
---|
686 | +#ifdef __cplusplus
|
---|
687 | +extern "C" {
|
---|
688 | +#endif /* __cplusplus */
|
---|
689 | +
|
---|
690 | +#if TARGET_OS_MAC
|
---|
691 | +# pragma pack(push,2)
|
---|
692 | +#endif
|
---|
693 | +
|
---|
694 | +#if 0
|
---|
695 | +#if defined(_MSDOS) || defined(_WIN32)
|
---|
696 | +#include <win-mac.h>
|
---|
697 | +#endif
|
---|
698 | +#endif
|
---|
699 | +
|
---|
700 | +#ifndef KRB5_CALLCONV
|
---|
701 | +#define KRB5_CALLCONV
|
---|
702 | +#define KRB5_CALLCONV_C
|
---|
703 | +#endif
|
---|
704 | +
|
---|
705 | +/*
|
---|
706 | + * First, include stddef.h to get size_t defined.
|
---|
707 | + */
|
---|
708 | +#include <stddef.h>
|
---|
709 | +
|
---|
710 | +/*
|
---|
711 | + * POSIX says that sys/types.h is where size_t is defined.
|
---|
712 | + */
|
---|
713 | +#include <sys/types.h>
|
---|
714 | +
|
---|
715 | +/*
|
---|
716 | + * $Id: gssapi.hin 20876 2008-10-15 21:58:43Z tlyu $
|
---|
717 | + */
|
---|
718 | +
|
---|
719 | +/*
|
---|
720 | + * First, define the three platform-dependent pointer types.
|
---|
721 | + */
|
---|
722 | +
|
---|
723 | +struct gss_name_struct;
|
---|
724 | +typedef struct gss_name_struct * gss_name_t;
|
---|
725 | +
|
---|
726 | +struct gss_cred_id_struct;
|
---|
727 | +typedef struct gss_cred_id_struct * gss_cred_id_t;
|
---|
728 | +
|
---|
729 | +struct gss_ctx_id_struct;
|
---|
730 | +typedef struct gss_ctx_id_struct * gss_ctx_id_t;
|
---|
731 | +
|
---|
732 | +/*
|
---|
733 | + * The following type must be defined as the smallest natural unsigned integer
|
---|
734 | + * supported by the platform that has at least 32 bits of precision.
|
---|
735 | + */
|
---|
736 | +typedef uint32_t gss_uint32;
|
---|
737 | +typedef int32_t gss_int32;
|
---|
738 | +
|
---|
739 | +#ifdef OM_STRING
|
---|
740 | +/*
|
---|
741 | + * We have included the xom.h header file. Use the definition for
|
---|
742 | + * OM_object identifier.
|
---|
743 | + */
|
---|
744 | +typedef OM_object_identifier gss_OID_desc, *gss_OID;
|
---|
745 | +#else /* OM_STRING */
|
---|
746 | +/*
|
---|
747 | + * We can't use X/Open definitions, so roll our own.
|
---|
748 | + */
|
---|
749 | +typedef gss_uint32 OM_uint32;
|
---|
750 | +
|
---|
751 | +typedef struct gss_OID_desc_struct {
|
---|
752 | + OM_uint32 length;
|
---|
753 | + void *elements;
|
---|
754 | +} gss_OID_desc, *gss_OID;
|
---|
755 | +#endif /* OM_STRING */
|
---|
756 | +
|
---|
757 | +typedef struct gss_OID_set_desc_struct {
|
---|
758 | + size_t count;
|
---|
759 | + gss_OID elements;
|
---|
760 | +} gss_OID_set_desc, *gss_OID_set;
|
---|
761 | +
|
---|
762 | +typedef struct gss_buffer_desc_struct {
|
---|
763 | + size_t length;
|
---|
764 | + void *value;
|
---|
765 | +} gss_buffer_desc, *gss_buffer_t;
|
---|
766 | +
|
---|
767 | +typedef struct gss_channel_bindings_struct {
|
---|
768 | + OM_uint32 initiator_addrtype;
|
---|
769 | + gss_buffer_desc initiator_address;
|
---|
770 | + OM_uint32 acceptor_addrtype;
|
---|
771 | + gss_buffer_desc acceptor_address;
|
---|
772 | + gss_buffer_desc application_data;
|
---|
773 | +} *gss_channel_bindings_t;
|
---|
774 | +
|
---|
775 | +/*
|
---|
776 | + * For now, define a QOP-type as an OM_uint32 (pending resolution of ongoing
|
---|
777 | + * discussions).
|
---|
778 | + */
|
---|
779 | +typedef OM_uint32 gss_qop_t;
|
---|
780 | +typedef int gss_cred_usage_t;
|
---|
781 | +
|
---|
782 | +/*
|
---|
783 | + * Flag bits for context-level services.
|
---|
784 | + */
|
---|
785 | +#define GSS_C_DELEG_FLAG 1
|
---|
786 | +#define GSS_C_MUTUAL_FLAG 2
|
---|
787 | +#define GSS_C_REPLAY_FLAG 4
|
---|
788 | +#define GSS_C_SEQUENCE_FLAG 8
|
---|
789 | +#define GSS_C_CONF_FLAG 16
|
---|
790 | +#define GSS_C_INTEG_FLAG 32
|
---|
791 | +#define GSS_C_ANON_FLAG 64
|
---|
792 | +#define GSS_C_PROT_READY_FLAG 128
|
---|
793 | +#define GSS_C_TRANS_FLAG 256
|
---|
794 | +#define GSS_C_DELEG_POLICY_FLAG 32768
|
---|
795 | +#define GSS_C_NO_UI_FLAG 0x80000000
|
---|
796 | +
|
---|
797 | +/*
|
---|
798 | + * Credential usage options
|
---|
799 | + */
|
---|
800 | +#define GSS_C_BOTH 0
|
---|
801 | +#define GSS_C_INITIATE 1
|
---|
802 | +#define GSS_C_ACCEPT 2
|
---|
803 | +
|
---|
804 | +#define GSS_C_OPTION_MASK 0xffff
|
---|
805 | +#define GSS_C_CRED_NO_UI 0x10000
|
---|
806 | +
|
---|
807 | +
|
---|
808 | +/*
|
---|
809 | + * Status code types for gss_display_status
|
---|
810 | + */
|
---|
811 | +#define GSS_C_GSS_CODE 1
|
---|
812 | +#define GSS_C_MECH_CODE 2
|
---|
813 | +
|
---|
814 | +/*
|
---|
815 | + * Various Null values.
|
---|
816 | + */
|
---|
817 | +#define GSS_C_NO_NAME ((gss_name_t) 0)
|
---|
818 | +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
|
---|
819 | +#define GSS_C_NO_OID ((gss_OID) 0)
|
---|
820 | +#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
|
---|
821 | +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
|
---|
822 | +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
|
---|
823 | +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
|
---|
824 | +#define GSS_C_EMPTY_BUFFER {0, NULL}
|
---|
825 | +
|
---|
826 | +/*
|
---|
827 | + * Some alternate names for a couple of the above values. These are defined
|
---|
828 | + * for V1 compatibility.
|
---|
829 | + */
|
---|
830 | +#define GSS_C_NULL_OID GSS_C_NO_OID
|
---|
831 | +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET
|
---|
832 | +
|
---|
833 | +/*
|
---|
834 | + * Define the default Quality of Protection for per-message services. Note
|
---|
835 | + * that an implementation that offers multiple levels of QOP may either reserve
|
---|
836 | + * a value (for example zero, as assumed here) to mean "default protection", or
|
---|
837 | + * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
|
---|
838 | + * QOP value. However a value of 0 should always be interpreted by a GSSAPI
|
---|
839 | + * implementation as a request for the default protection level.
|
---|
840 | + */
|
---|
841 | +#define GSS_C_QOP_DEFAULT 0
|
---|
842 | +
|
---|
843 | +/*
|
---|
844 | + * Expiration time of 2^32-1 seconds means infinite lifetime for a
|
---|
845 | + * credential or security context
|
---|
846 | + */
|
---|
847 | +#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
|
---|
848 | +
|
---|
849 | +
|
---|
850 | +/* Major status codes */
|
---|
851 | +
|
---|
852 | +#define GSS_S_COMPLETE 0
|
---|
853 | +
|
---|
854 | +/*
|
---|
855 | + * Some "helper" definitions to make the status code macros obvious.
|
---|
856 | + */
|
---|
857 | +#define GSS_C_CALLING_ERROR_OFFSET 24
|
---|
858 | +#define GSS_C_ROUTINE_ERROR_OFFSET 16
|
---|
859 | +#define GSS_C_SUPPLEMENTARY_OFFSET 0
|
---|
860 | +#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
|
---|
861 | +#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
|
---|
862 | +#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
|
---|
863 | +
|
---|
864 | +/*
|
---|
865 | + * The macros that test status codes for error conditions. Note that the
|
---|
866 | + * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
|
---|
867 | + * evaluates its argument only once.
|
---|
868 | + */
|
---|
869 | +#define GSS_CALLING_ERROR(x) \
|
---|
870 | + ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
|
---|
871 | +#define GSS_ROUTINE_ERROR(x) \
|
---|
872 | + ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
|
---|
873 | +#define GSS_SUPPLEMENTARY_INFO(x) \
|
---|
874 | + ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
|
---|
875 | +#define GSS_ERROR(x) \
|
---|
876 | + ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
|
---|
877 | + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
|
---|
878 | +
|
---|
879 | +/*
|
---|
880 | + * Now the actual status code definitions
|
---|
881 | + */
|
---|
882 | +
|
---|
883 | +/*
|
---|
884 | + * Calling errors:
|
---|
885 | + */
|
---|
886 | +#define GSS_S_CALL_INACCESSIBLE_READ \
|
---|
887 | + (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
|
---|
888 | +#define GSS_S_CALL_INACCESSIBLE_WRITE \
|
---|
889 | + (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
|
---|
890 | +#define GSS_S_CALL_BAD_STRUCTURE \
|
---|
891 | + (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
|
---|
892 | +
|
---|
893 | +/*
|
---|
894 | + * Routine errors:
|
---|
895 | + */
|
---|
896 | +#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
897 | +#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
898 | +#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
899 | +#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
900 | +#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
901 | +#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
902 | +#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
903 | +#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
904 | +#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
905 | +#define GSS_S_DEFECTIVE_CREDENTIAL \
|
---|
906 | + (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
907 | +#define GSS_S_CREDENTIALS_EXPIRED \
|
---|
908 | + (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
909 | +#define GSS_S_CONTEXT_EXPIRED \
|
---|
910 | + (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
911 | +#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
912 | +#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
913 | +#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
914 | +#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
915 | +#define GSS_S_DUPLICATE_ELEMENT \
|
---|
916 | + (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
917 | +#define GSS_S_NAME_NOT_MN \
|
---|
918 | + (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
|
---|
919 | +
|
---|
920 | +/*
|
---|
921 | + * Supplementary info bits:
|
---|
922 | + */
|
---|
923 | +#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
|
---|
924 | +#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
|
---|
925 | +#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
|
---|
926 | +#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
|
---|
927 | +#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
|
---|
928 | +
|
---|
929 | +
|
---|
930 | +/*
|
---|
931 | + * Finally, function prototypes for the GSSAPI routines.
|
---|
932 | + */
|
---|
933 | +
|
---|
934 | +#if defined (_WIN32) && defined (_MSC_VER)
|
---|
935 | +# ifdef GSS_DLL_FILE
|
---|
936 | +# define GSS_DLLIMP __declspec(dllexport)
|
---|
937 | +# else
|
---|
938 | +# define GSS_DLLIMP __declspec(dllimport)
|
---|
939 | +# endif
|
---|
940 | +#else
|
---|
941 | +# define GSS_DLLIMP
|
---|
942 | +#endif
|
---|
943 | +
|
---|
944 | +/* Reserved static storage for GSS_oids. Comments are quotes from RFC 2744.
|
---|
945 | + *
|
---|
946 | + * The implementation must reserve static storage for a
|
---|
947 | + * gss_OID_desc object containing the value
|
---|
948 | + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"},
|
---|
949 | + * corresponding to an object-identifier value of
|
---|
950 | + * {iso(1) member-body(2) United States(840) mit(113554)
|
---|
951 | + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant
|
---|
952 | + * GSS_C_NT_USER_NAME should be initialized to point
|
---|
953 | + * to that gss_OID_desc.
|
---|
954 | + */
|
---|
955 | +GSS_DLLIMP extern gss_OID GSS_C_NT_USER_NAME;
|
---|
956 | +
|
---|
957 | +/*
|
---|
958 | + * The implementation must reserve static storage for a
|
---|
959 | + * gss_OID_desc object containing the value
|
---|
960 | + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"},
|
---|
961 | + * corresponding to an object-identifier value of
|
---|
962 | + * {iso(1) member-body(2) United States(840) mit(113554)
|
---|
963 | + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
|
---|
964 | + * The constant GSS_C_NT_MACHINE_UID_NAME should be
|
---|
965 | + * initialized to point to that gss_OID_desc.
|
---|
966 | + */
|
---|
967 | +GSS_DLLIMP extern gss_OID GSS_C_NT_MACHINE_UID_NAME;
|
---|
968 | +
|
---|
969 | +/*
|
---|
970 | + * The implementation must reserve static storage for a
|
---|
971 | + * gss_OID_desc object containing the value
|
---|
972 | + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"},
|
---|
973 | + * corresponding to an object-identifier value of
|
---|
974 | + * {iso(1) member-body(2) United States(840) mit(113554)
|
---|
975 | + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
|
---|
976 | + * The constant GSS_C_NT_STRING_UID_NAME should be
|
---|
977 | + * initialized to point to that gss_OID_desc.
|
---|
978 | + */
|
---|
979 | +GSS_DLLIMP extern gss_OID GSS_C_NT_STRING_UID_NAME;
|
---|
980 | +
|
---|
981 | +/*
|
---|
982 | + * The implementation must reserve static storage for a
|
---|
983 | + * gss_OID_desc object containing the value
|
---|
984 | + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
|
---|
985 | + * corresponding to an object-identifier value of
|
---|
986 | + * {iso(1) org(3) dod(6) internet(1) security(5)
|
---|
987 | + * nametypes(6) gss-host-based-services(2)). The constant
|
---|
988 | + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point
|
---|
989 | + * to that gss_OID_desc. This is a deprecated OID value, and
|
---|
990 | + * implementations wishing to support hostbased-service names
|
---|
991 | + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID,
|
---|
992 | + * defined below, to identify such names;
|
---|
993 | + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym
|
---|
994 | + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input
|
---|
995 | + * parameter, but should not be emitted by GSS-API
|
---|
996 | + * implementations
|
---|
997 | + */
|
---|
998 | +GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
|
---|
999 | +
|
---|
1000 | +/*
|
---|
1001 | + * The implementation must reserve static storage for a
|
---|
1002 | + * gss_OID_desc object containing the value
|
---|
1003 | + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
|
---|
1004 | + * "\x01\x02\x01\x04"}, corresponding to an
|
---|
1005 | + * object-identifier value of {iso(1) member-body(2)
|
---|
1006 | + * Unites States(840) mit(113554) infosys(1) gssapi(2)
|
---|
1007 | + * generic(1) service_name(4)}. The constant
|
---|
1008 | + * GSS_C_NT_HOSTBASED_SERVICE should be initialized
|
---|
1009 | + * to point to that gss_OID_desc.
|
---|
1010 | + */
|
---|
1011 | +static gss_OID *p_GSS_C_NT_HOSTBASED_SERVICE;
|
---|
1012 | +
|
---|
1013 | +/*
|
---|
1014 | + * The implementation must reserve static storage for a
|
---|
1015 | + * gss_OID_desc object containing the value
|
---|
1016 | + * {6, (void *)"\x2b\x06\01\x05\x06\x03"},
|
---|
1017 | + * corresponding to an object identifier value of
|
---|
1018 | + * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
|
---|
1019 | + * 6(nametypes), 3(gss-anonymous-name)}. The constant
|
---|
1020 | + * and GSS_C_NT_ANONYMOUS should be initialized to point
|
---|
1021 | + * to that gss_OID_desc.
|
---|
1022 | + */
|
---|
1023 | +GSS_DLLIMP extern gss_OID GSS_C_NT_ANONYMOUS;
|
---|
1024 | +
|
---|
1025 | +
|
---|
1026 | +/*
|
---|
1027 | + * The implementation must reserve static storage for a
|
---|
1028 | + * gss_OID_desc object containing the value
|
---|
1029 | + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
|
---|
1030 | + * corresponding to an object-identifier value of
|
---|
1031 | + * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
|
---|
1032 | + * 6(nametypes), 4(gss-api-exported-name)}. The constant
|
---|
1033 | + * GSS_C_NT_EXPORT_NAME should be initialized to point
|
---|
1034 | + * to that gss_OID_desc.
|
---|
1035 | + */
|
---|
1036 | +GSS_DLLIMP extern gss_OID GSS_C_NT_EXPORT_NAME;
|
---|
1037 | +
|
---|
1038 | +/* Function Prototypes */
|
---|
1039 | +
|
---|
1040 | +static OM_uint32 KRB5_CALLCONV
|
---|
1041 | +(*p_gss_init_sec_context)(
|
---|
1042 | + OM_uint32 *, /* minor_status */
|
---|
1043 | + gss_cred_id_t, /* claimant_cred_handle */
|
---|
1044 | + gss_ctx_id_t *, /* context_handle */
|
---|
1045 | + gss_name_t, /* target_name */
|
---|
1046 | + gss_OID, /* mech_type (used to be const) */
|
---|
1047 | + OM_uint32, /* req_flags */
|
---|
1048 | + OM_uint32, /* time_req */
|
---|
1049 | + gss_channel_bindings_t, /* input_chan_bindings */
|
---|
1050 | + gss_buffer_t, /* input_token */
|
---|
1051 | + gss_OID *, /* actual_mech_type */
|
---|
1052 | + gss_buffer_t, /* output_token */
|
---|
1053 | + OM_uint32 *, /* ret_flags */
|
---|
1054 | + OM_uint32 *) /* time_rec */
|
---|
1055 | + = NULL;
|
---|
1056 | +
|
---|
1057 | +
|
---|
1058 | +static OM_uint32 KRB5_CALLCONV
|
---|
1059 | +(*p_gss_delete_sec_context)(
|
---|
1060 | + OM_uint32 *, /* minor_status */
|
---|
1061 | + gss_ctx_id_t *, /* context_handle */
|
---|
1062 | + gss_buffer_t); /* output_token */
|
---|
1063 | +
|
---|
1064 | +
|
---|
1065 | +static OM_uint32 KRB5_CALLCONV
|
---|
1066 | +(*p_gss_wrap)(
|
---|
1067 | + OM_uint32 *, /* minor_status */
|
---|
1068 | + gss_ctx_id_t, /* context_handle */
|
---|
1069 | + int, /* conf_req_flag */
|
---|
1070 | + gss_qop_t, /* qop_req */
|
---|
1071 | + gss_buffer_t, /* input_message_buffer */
|
---|
1072 | + int *, /* conf_state */
|
---|
1073 | + gss_buffer_t) /* output_message_buffer */
|
---|
1074 | + = NULL;
|
---|
1075 | +
|
---|
1076 | +static OM_uint32 KRB5_CALLCONV
|
---|
1077 | +(*p_gss_unwrap)(
|
---|
1078 | + OM_uint32 *, /* minor_status */
|
---|
1079 | + gss_ctx_id_t, /* context_handle */
|
---|
1080 | + gss_buffer_t, /* input_message_buffer */
|
---|
1081 | + gss_buffer_t, /* output_message_buffer */
|
---|
1082 | + int *, /* conf_state */
|
---|
1083 | + gss_qop_t *) /* qop_state */
|
---|
1084 | + = NULL;
|
---|
1085 | +
|
---|
1086 | +
|
---|
1087 | +static OM_uint32 KRB5_CALLCONV
|
---|
1088 | +(*p_gss_display_status)(
|
---|
1089 | + OM_uint32 *, /* minor_status */
|
---|
1090 | + OM_uint32, /* status_value */
|
---|
1091 | + int, /* status_type */
|
---|
1092 | + gss_OID, /* mech_type (used to be const) */
|
---|
1093 | + OM_uint32 *, /* message_context */
|
---|
1094 | + gss_buffer_t) /* status_string */
|
---|
1095 | + = NULL;
|
---|
1096 | +
|
---|
1097 | +
|
---|
1098 | +static OM_uint32 KRB5_CALLCONV
|
---|
1099 | +(*p_gss_import_name)(
|
---|
1100 | + OM_uint32 *, /* minor_status */
|
---|
1101 | + gss_buffer_t, /* input_name_buffer */
|
---|
1102 | + gss_OID, /* input_name_type(used to be const) */
|
---|
1103 | + gss_name_t *) /* output_name */
|
---|
1104 | + = NULL;
|
---|
1105 | +
|
---|
1106 | +static OM_uint32 KRB5_CALLCONV
|
---|
1107 | +(*p_gss_release_name)(
|
---|
1108 | + OM_uint32 *, /* minor_status */
|
---|
1109 | + gss_name_t *) /* input_name */
|
---|
1110 | + = NULL;
|
---|
1111 | +
|
---|
1112 | +static OM_uint32 KRB5_CALLCONV
|
---|
1113 | +(*p_gss_release_buffer)(
|
---|
1114 | + OM_uint32 *, /* minor_status */
|
---|
1115 | + gss_buffer_t) /* buffer */
|
---|
1116 | + = NULL;
|
---|
1117 | +
|
---|
1118 | +static OM_uint32 KRB5_CALLCONV
|
---|
1119 | +(*p_gss_wrap_size_limit)(
|
---|
1120 | + OM_uint32 *, /* minor_status */
|
---|
1121 | + gss_ctx_id_t, /* context_handle */
|
---|
1122 | + int, /* conf_req_flag */
|
---|
1123 | + gss_qop_t, /* qop_req */
|
---|
1124 | + OM_uint32, /* req_output_size */
|
---|
1125 | + OM_uint32 *) /* max_input_size */
|
---|
1126 | + = NULL;
|
---|
1127 | +
|
---|
1128 | +#if TARGET_OS_MAC
|
---|
1129 | +# pragma pack(pop)
|
---|
1130 | +#endif
|
---|
1131 | +
|
---|
1132 | +#ifdef __cplusplus
|
---|
1133 | +}
|
---|
1134 | +#endif
|
---|
1135 | +
|
---|
1136 | +/* XXXX these are not part of the GSSAPI C bindings! (but should be) */
|
---|
1137 | +
|
---|
1138 | +#define GSS_CALLING_ERROR_FIELD(x) \
|
---|
1139 | + (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
|
---|
1140 | +#define GSS_ROUTINE_ERROR_FIELD(x) \
|
---|
1141 | + (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
|
---|
1142 | +#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
|
---|
1143 | + (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
|
---|
1144 | +
|
---|
1145 | +/* XXXX This is a necessary evil until the spec is fixed */
|
---|
1146 | +#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
|
---|
1147 | +
|
---|
1148 | +static int tried_load = 0;
|
---|
1149 | +
|
---|
1150 | +static struct symbol_list
|
---|
1151 | +{
|
---|
1152 | + const char *symname;
|
---|
1153 | + void **symptr;
|
---|
1154 | +} gssapi_symlist[] =
|
---|
1155 | +{
|
---|
1156 | + { "gss_init_sec_context", (void **) &p_gss_init_sec_context },
|
---|
1157 | + { "gss_delete_sec_context", (void **) &p_gss_delete_sec_context },
|
---|
1158 | + { "gss_release_buffer", (void **) &p_gss_release_buffer },
|
---|
1159 | + { "gss_release_name", (void **) &p_gss_release_name },
|
---|
1160 | + { "gss_display_status", (void **) &p_gss_display_status },
|
---|
1161 | + { "gss_import_name", (void **) &p_gss_import_name },
|
---|
1162 | + { "gss_wrap", (void **) &p_gss_wrap },
|
---|
1163 | + { "gss_unwrap", (void **) &p_gss_unwrap },
|
---|
1164 | + { "gss_wrap_size_limit", (void **) &p_gss_wrap_size_limit },
|
---|
1165 | + { "GSS_C_NT_HOSTBASED_SERVICE", (void **) &p_GSS_C_NT_HOSTBASED_SERVICE },
|
---|
1166 | + { NULL, NULL},
|
---|
1167 | +};
|
---|
1168 | +
|
---|
1169 | +static wxDynamicLibrary gsslib;
|
---|
1170 | +static wxString gsslibname =
|
---|
1171 | +#ifdef DEFAULT_GSS_LIBRARY
|
---|
1172 | + DEFAULT_GSS_LIBRARY ;
|
---|
1173 | +#elif __WXMAC__
|
---|
1174 | + "/usr/lib/libgssapi_krb5.dylib";
|
---|
1175 | +#elif __WXMSW__
|
---|
1176 | + "C:\\Program Files\\MIT Kerberos\\GSSAPI32.DLL";
|
---|
1177 | +#else
|
---|
1178 | + "/usr/lib/libgssapi_krb5.so";
|
---|
1179 | +#endif
|
---|
1180 | +
|
---|
1181 | +static wxString gssloaderr;
|
---|
1182 | +
|
---|
1183 | +static void LogGssError(CControlSocket *psocket, OM_uint32 maj, OM_uint32 min);
|
---|
1184 | +
|
---|
1185 | +bool IsGssLoaded(void)
|
---|
1186 | +{
|
---|
1187 | + if (! COptions::Get()->GetOptionVal(OPTION_GSS_ENABLE))
|
---|
1188 | + return false;
|
---|
1189 | +
|
---|
1190 | + if (!gsslib.IsLoaded() && !tried_load) {
|
---|
1191 | + tried_load = 1;
|
---|
1192 | +
|
---|
1193 | + wxString libname = COptions::Get()->GetOption(OPTION_GSS_LIBRARY);
|
---|
1194 | +
|
---|
1195 | + return LoadGssLibrary(libname.IsEmpty() ? gsslibname : libname);
|
---|
1196 | + }
|
---|
1197 | +
|
---|
1198 | + return gsslib.IsLoaded();
|
---|
1199 | +}
|
---|
1200 | +
|
---|
1201 | +bool LoadGssLibrary(const wxString &libname)
|
---|
1202 | +{
|
---|
1203 | + int i;
|
---|
1204 | +
|
---|
1205 | + tried_load = 1;
|
---|
1206 | +
|
---|
1207 | + if (gsslib.IsLoaded()) {
|
---|
1208 | + gsslib.Unload();
|
---|
1209 | +
|
---|
1210 | + for (i = 0; gssapi_symlist[i].symname != NULL; i++)
|
---|
1211 | + *gssapi_symlist[i].symptr = NULL;
|
---|
1212 | + }
|
---|
1213 | +
|
---|
1214 | + gsslibname = libname;
|
---|
1215 | +
|
---|
1216 | +#ifdef __WXMSW__
|
---|
1217 | + /*
|
---|
1218 | + * On Windows we need to set the DLL path so that the GSSAPI library
|
---|
1219 | + * can pull in any necessary symbols from other libraries (such as
|
---|
1220 | + * the Kerberos library). Set the path based on the directory of
|
---|
1221 | + * the GSSAPI library.
|
---|
1222 | + */
|
---|
1223 | +
|
---|
1224 | + wxFileName dirname(libname);
|
---|
1225 | + wxString dir = dirname.GetPath();
|
---|
1226 | +
|
---|
1227 | + SetDllDirectory(dir.t_str());
|
---|
1228 | +#endif
|
---|
1229 | +
|
---|
1230 | + if (gsslib.Load(gsslibname, wxDL_DEFAULT | wxDL_VERBATIM) == true) {
|
---|
1231 | + for (i = 0; gssapi_symlist[i].symname != NULL; i++)
|
---|
1232 | + {
|
---|
1233 | + *gssapi_symlist[i].symptr =
|
---|
1234 | + gsslib.GetSymbol(gssapi_symlist[i].symname);
|
---|
1235 | +
|
---|
1236 | + if (! *gssapi_symlist[i].symptr) {
|
---|
1237 | + gsslib.Unload();
|
---|
1238 | + gssloaderr =
|
---|
1239 | + wxString::Format("Unable to load "
|
---|
1240 | + "symbol %s from "
|
---|
1241 | + "library %s",
|
---|
1242 | + gssapi_symlist[i].symname,
|
---|
1243 | + gsslibname);
|
---|
1244 | + return false;
|
---|
1245 | + }
|
---|
1246 | + }
|
---|
1247 | + } else {
|
---|
1248 | + gssloaderr = wxString::Format("Load of %s failed", gsslibname);
|
---|
1249 | + return false;
|
---|
1250 | + }
|
---|
1251 | +
|
---|
1252 | + return true;
|
---|
1253 | +}
|
---|
1254 | +
|
---|
1255 | +wxString GetGssLibraryName(void)
|
---|
1256 | +{
|
---|
1257 | + return gsslibname;
|
---|
1258 | +}
|
---|
1259 | +
|
---|
1260 | +wxString GetGssLoadError(void)
|
---|
1261 | +{
|
---|
1262 | + return gssloaderr;
|
---|
1263 | +}
|
---|
1264 | +
|
---|
1265 | +bool GssInitSecContext(CControlSocket *psocket, void **context, void *name,
|
---|
1266 | + bool delegate, const wxString &input_token,
|
---|
1267 | + wxString *output_token, bool *complete)
|
---|
1268 | +{
|
---|
1269 | + OM_uint32 maj_stat, min_stat;
|
---|
1270 | + gss_buffer_desc recv_token = GSS_C_EMPTY_BUFFER,
|
---|
1271 | + send_token = GSS_C_EMPTY_BUFFER;
|
---|
1272 | + wxMemoryBuffer decoded_recv;
|
---|
1273 | +
|
---|
1274 | + if (! p_gss_init_sec_context)
|
---|
1275 | + {
|
---|
1276 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_init_sec_context is NULL!"));
|
---|
1277 | + return false;
|
---|
1278 | + }
|
---|
1279 | +
|
---|
1280 | + if (input_token.Length() > 0) {
|
---|
1281 | + decoded_recv = wxBase64Decode(input_token);
|
---|
1282 | + if (!decoded_recv) {
|
---|
1283 | + psocket->LogMessage(MessageType::Error, _("Unable to decode base64 data when calling gss_init_sec_context"));
|
---|
1284 | + return false;
|
---|
1285 | + }
|
---|
1286 | +
|
---|
1287 | + recv_token.value = decoded_recv.GetData();
|
---|
1288 | + recv_token.length = decoded_recv.GetDataLen();
|
---|
1289 | + }
|
---|
1290 | +
|
---|
1291 | + maj_stat = p_gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL,
|
---|
1292 | + (gss_ctx_id_t *) context,
|
---|
1293 | + (gss_name_t) name,
|
---|
1294 | + GSS_C_NO_OID,
|
---|
1295 | + GSS_C_MUTUAL_FLAG |
|
---|
1296 | + GSS_C_REPLAY_FLAG |
|
---|
1297 | + (delegate ? GSS_C_DELEG_FLAG : 0), 0,
|
---|
1298 | + GSS_C_NO_CHANNEL_BINDINGS,
|
---|
1299 | + &recv_token, NULL, &send_token,
|
---|
1300 | + NULL, NULL);
|
---|
1301 | +
|
---|
1302 | + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
|
---|
1303 | + {
|
---|
1304 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1305 | + return false;
|
---|
1306 | + }
|
---|
1307 | +
|
---|
1308 | + if (complete)
|
---|
1309 | + {
|
---|
1310 | + *complete = (maj_stat == GSS_S_COMPLETE) ? true : false;
|
---|
1311 | + }
|
---|
1312 | +
|
---|
1313 | + if (send_token.length > 0)
|
---|
1314 | + {
|
---|
1315 | + *output_token = wxBase64Encode((char *) send_token.value,
|
---|
1316 | + send_token.length);
|
---|
1317 | + p_gss_release_buffer(&min_stat, &send_token);
|
---|
1318 | + }
|
---|
1319 | +
|
---|
1320 | + return true;
|
---|
1321 | +}
|
---|
1322 | +
|
---|
1323 | +bool GssImportName(CControlSocket *psocket, const wxString& name,
|
---|
1324 | + void **target_ret)
|
---|
1325 | +{
|
---|
1326 | + OM_uint32 maj_stat, min_stat;
|
---|
1327 | + gss_buffer_desc name_buf;
|
---|
1328 | +
|
---|
1329 | + if (!p_gss_import_name || !p_GSS_C_NT_HOSTBASED_SERVICE)
|
---|
1330 | + {
|
---|
1331 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_import_name or p_GSS_C_NT_HOSTBASED_SERVICE is NULL!"));
|
---|
1332 | + return false;
|
---|
1333 | + }
|
---|
1334 | +
|
---|
1335 | + std::string temp = name.ToStdString();
|
---|
1336 | +
|
---|
1337 | + name_buf.value = (char *) temp.c_str();
|
---|
1338 | + name_buf.length = name.Length();
|
---|
1339 | +
|
---|
1340 | + maj_stat = p_gss_import_name(&min_stat, &name_buf,
|
---|
1341 | + *p_GSS_C_NT_HOSTBASED_SERVICE,
|
---|
1342 | + (gss_name_t *) target_ret);
|
---|
1343 | +
|
---|
1344 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1345 | + {
|
---|
1346 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1347 | + return false;
|
---|
1348 | + }
|
---|
1349 | +
|
---|
1350 | + return true;
|
---|
1351 | +}
|
---|
1352 | +
|
---|
1353 | +bool
|
---|
1354 | +GssWrap(CControlSocket *psocket, void *context, bool encrypt,
|
---|
1355 | + const wxCharBuffer &inbuf, wxString *outbuf)
|
---|
1356 | +{
|
---|
1357 | + OM_uint32 maj_stat, min_stat;
|
---|
1358 | + gss_buffer_desc in_wrap, out_wrap = GSS_C_EMPTY_BUFFER;
|
---|
1359 | + int conf_state;
|
---|
1360 | + wxMemoryBuffer encbuf;
|
---|
1361 | +
|
---|
1362 | + if (!p_gss_wrap)
|
---|
1363 | + {
|
---|
1364 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_wrap is NULL!"));
|
---|
1365 | + return false;
|
---|
1366 | + }
|
---|
1367 | +
|
---|
1368 | + in_wrap.value = (char *) inbuf.data();
|
---|
1369 | + in_wrap.length = inbuf.length() + 1;
|
---|
1370 | +
|
---|
1371 | + maj_stat = p_gss_wrap(&min_stat, (gss_ctx_id_t) context,
|
---|
1372 | + encrypt ? 1 : 0, GSS_C_QOP_DEFAULT, &in_wrap,
|
---|
1373 | + &conf_state, &out_wrap);
|
---|
1374 | +
|
---|
1375 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1376 | + {
|
---|
1377 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1378 | + return false;
|
---|
1379 | + }
|
---|
1380 | +
|
---|
1381 | + encbuf.AppendData(out_wrap.value, out_wrap.length);
|
---|
1382 | +
|
---|
1383 | + *outbuf = wxBase64Encode(encbuf);
|
---|
1384 | +
|
---|
1385 | + p_gss_release_buffer(&min_stat, &out_wrap);
|
---|
1386 | +
|
---|
1387 | + return true;
|
---|
1388 | +}
|
---|
1389 | +
|
---|
1390 | +bool
|
---|
1391 | +GssWrap(CControlSocket *psocket, void *context, bool encrypt,
|
---|
1392 | + const unsigned char *inbuf, size_t inbuflen, unsigned char **outbuf,
|
---|
1393 | + size_t *outbufsize, size_t *outbuflen, size_t offset)
|
---|
1394 | +{
|
---|
1395 | + OM_uint32 maj_stat, min_stat;
|
---|
1396 | + gss_buffer_desc in_wrap, out_wrap = GSS_C_EMPTY_BUFFER;
|
---|
1397 | + int conf_state;
|
---|
1398 | +
|
---|
1399 | + if (!p_gss_wrap)
|
---|
1400 | + {
|
---|
1401 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_wrap is NULL!"));
|
---|
1402 | + return false;
|
---|
1403 | + }
|
---|
1404 | +
|
---|
1405 | + in_wrap.value = (void *) inbuf;
|
---|
1406 | + in_wrap.length = inbuflen;
|
---|
1407 | +
|
---|
1408 | + maj_stat = p_gss_wrap(&min_stat, (gss_ctx_id_t) context,
|
---|
1409 | + encrypt ? 1 : 0, GSS_C_QOP_DEFAULT, &in_wrap,
|
---|
1410 | + &conf_state, &out_wrap);
|
---|
1411 | +
|
---|
1412 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1413 | + {
|
---|
1414 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1415 | + return false;
|
---|
1416 | + }
|
---|
1417 | +
|
---|
1418 | + if (out_wrap.length > *outbufsize + offset) {
|
---|
1419 | + *outbufsize = out_wrap.length + offset;
|
---|
1420 | + *outbuf = (unsigned char *) realloc(*outbuf, *outbufsize);
|
---|
1421 | + }
|
---|
1422 | +
|
---|
1423 | + memcpy(*outbuf + offset, out_wrap.value, out_wrap.length);
|
---|
1424 | +
|
---|
1425 | + *outbuflen = out_wrap.length;
|
---|
1426 | +
|
---|
1427 | + p_gss_release_buffer(&min_stat, &out_wrap);
|
---|
1428 | +
|
---|
1429 | + return true;
|
---|
1430 | +}
|
---|
1431 | +
|
---|
1432 | +bool
|
---|
1433 | +GssUnwrap(CControlSocket *psocket, void *context, const wxString& inbuf,
|
---|
1434 | + wxMemoryBuffer *outbuf, bool *encrypt)
|
---|
1435 | +{
|
---|
1436 | + OM_uint32 maj_stat, min_stat;
|
---|
1437 | + gss_buffer_desc in_wrap, out_wrap;
|
---|
1438 | + int conf_level;
|
---|
1439 | +
|
---|
1440 | + if (!p_gss_unwrap)
|
---|
1441 | + {
|
---|
1442 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_unwrap is NULL!"));
|
---|
1443 | + return false;
|
---|
1444 | + }
|
---|
1445 | +
|
---|
1446 | + wxMemoryBuffer indecbuf = wxBase64Decode(inbuf);
|
---|
1447 | +
|
---|
1448 | + if (!indecbuf)
|
---|
1449 | + {
|
---|
1450 | + psocket->LogMessage(MessageType::Error, _("Unable to base64-decode message response data!"));
|
---|
1451 | + return false;
|
---|
1452 | + }
|
---|
1453 | +
|
---|
1454 | + in_wrap.value = indecbuf.GetData();
|
---|
1455 | + in_wrap.length = indecbuf.GetDataLen();
|
---|
1456 | +
|
---|
1457 | + maj_stat = p_gss_unwrap(&min_stat, (gss_ctx_id_t) context, &in_wrap,
|
---|
1458 | + &out_wrap, &conf_level, NULL);
|
---|
1459 | +
|
---|
1460 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1461 | + {
|
---|
1462 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1463 | + return false;
|
---|
1464 | + }
|
---|
1465 | +
|
---|
1466 | + if (encrypt)
|
---|
1467 | + {
|
---|
1468 | + *encrypt = conf_level != 0;
|
---|
1469 | + }
|
---|
1470 | +
|
---|
1471 | + outbuf->Clear();
|
---|
1472 | + outbuf->AppendData(out_wrap.value, out_wrap.length);
|
---|
1473 | +
|
---|
1474 | + p_gss_release_buffer(&min_stat, &out_wrap);
|
---|
1475 | +
|
---|
1476 | + return true;
|
---|
1477 | +}
|
---|
1478 | +
|
---|
1479 | +bool GssUnwrap(CControlSocket* psocket, void *context, unsigned char *inbuf,
|
---|
1480 | + size_t inbuflen, unsigned char **outbuf, size_t *outbuflen,
|
---|
1481 | + size_t *retbufsize)
|
---|
1482 | +{
|
---|
1483 | + OM_uint32 maj_stat, min_stat;
|
---|
1484 | + gss_buffer_desc in_wrap, out_wrap;
|
---|
1485 | + int conf_level;
|
---|
1486 | +
|
---|
1487 | + if (!p_gss_unwrap)
|
---|
1488 | + {
|
---|
1489 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_unwrap is NULL!"));
|
---|
1490 | + return false;
|
---|
1491 | + }
|
---|
1492 | +
|
---|
1493 | + in_wrap.value = inbuf;
|
---|
1494 | + in_wrap.length = inbuflen;
|
---|
1495 | +
|
---|
1496 | + maj_stat = p_gss_unwrap(&min_stat, (gss_ctx_id_t) context, &in_wrap,
|
---|
1497 | + &out_wrap, &conf_level, NULL);
|
---|
1498 | +
|
---|
1499 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1500 | + {
|
---|
1501 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1502 | + return false;
|
---|
1503 | + }
|
---|
1504 | +
|
---|
1505 | + if (out_wrap.length > *outbuflen) {
|
---|
1506 | + *outbuf = (unsigned char *) realloc(*outbuf, out_wrap.length);
|
---|
1507 | + *outbuflen = out_wrap.length;
|
---|
1508 | + }
|
---|
1509 | +
|
---|
1510 | + memcpy(*outbuf, out_wrap.value, out_wrap.length);
|
---|
1511 | + *retbufsize = out_wrap.length;
|
---|
1512 | +
|
---|
1513 | + p_gss_release_buffer(&min_stat, &out_wrap);
|
---|
1514 | +
|
---|
1515 | + return true;
|
---|
1516 | +}
|
---|
1517 | +
|
---|
1518 | +bool
|
---|
1519 | +GssWrapSizeLimit(CControlSocket *psocket, void *context, size_t output_size,
|
---|
1520 | + size_t *max_input_size)
|
---|
1521 | +{
|
---|
1522 | + OM_uint32 maj_stat, min_stat;
|
---|
1523 | + OM_uint32 req_insize;
|
---|
1524 | +
|
---|
1525 | + if (!p_gss_wrap_size_limit)
|
---|
1526 | + {
|
---|
1527 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_wrap_size_limit is NULL!"));
|
---|
1528 | + return false;
|
---|
1529 | + }
|
---|
1530 | +
|
---|
1531 | + maj_stat = p_gss_wrap_size_limit(&min_stat, (gss_ctx_id_t) context, 1,
|
---|
1532 | + GSS_C_QOP_DEFAULT, output_size,
|
---|
1533 | + &req_insize);
|
---|
1534 | +
|
---|
1535 | + if (maj_stat != GSS_S_COMPLETE)
|
---|
1536 | + {
|
---|
1537 | + LogGssError(psocket, maj_stat, min_stat);
|
---|
1538 | + return false;
|
---|
1539 | + }
|
---|
1540 | +
|
---|
1541 | + *max_input_size = req_insize;
|
---|
1542 | +
|
---|
1543 | + return true;
|
---|
1544 | +}
|
---|
1545 | +
|
---|
1546 | +void
|
---|
1547 | +GssReleaseName(CControlSocket* psocket, void **name)
|
---|
1548 | +{
|
---|
1549 | + OM_uint32 maj_stat, min_stat;
|
---|
1550 | +
|
---|
1551 | + if (!p_gss_release_name)
|
---|
1552 | + {
|
---|
1553 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_release_buffer is NULL!"));
|
---|
1554 | + return;
|
---|
1555 | + }
|
---|
1556 | +
|
---|
1557 | + maj_stat = p_gss_release_name(&min_stat, (gss_name_t *) name);
|
---|
1558 | +
|
---|
1559 | + return;
|
---|
1560 | +}
|
---|
1561 | +
|
---|
1562 | +static void
|
---|
1563 | +LogGssError(CControlSocket *psocket, OM_uint32 maj, OM_uint32 min)
|
---|
1564 | +{
|
---|
1565 | + OM_uint32 maj_stat, min_stat, message_context = 0;
|
---|
1566 | + gss_buffer_desc status_string;
|
---|
1567 | +
|
---|
1568 | + if (!p_gss_display_status)
|
---|
1569 | + {
|
---|
1570 | + psocket->LogMessage(MessageType::Error, _("Internal Error: p_gss_display_status is NULL!"));
|
---|
1571 | + return;
|
---|
1572 | + }
|
---|
1573 | +
|
---|
1574 | + do {
|
---|
1575 | + maj_stat = p_gss_display_status(&min_stat, maj,
|
---|
1576 | + GSS_C_GSS_CODE, GSS_C_NO_OID,
|
---|
1577 | + &message_context,
|
---|
1578 | + &status_string);
|
---|
1579 | +
|
---|
1580 | + if (maj_stat == GSS_S_COMPLETE)
|
---|
1581 | + {
|
---|
1582 | + psocket->LogMessage(MessageType::Error, _T("GSSAPI Error Major Status: %.*s"),
|
---|
1583 | + (int) status_string.length,
|
---|
1584 | + (char *) status_string.value);
|
---|
1585 | + p_gss_release_buffer(&min_stat, &status_string);
|
---|
1586 | + }
|
---|
1587 | + } while (message_context != 0);
|
---|
1588 | +
|
---|
1589 | + do {
|
---|
1590 | + maj_stat = p_gss_display_status(&min_stat, min,
|
---|
1591 | + GSS_C_MECH_CODE, GSS_C_NO_OID,
|
---|
1592 | + &message_context,
|
---|
1593 | + &status_string);
|
---|
1594 | +
|
---|
1595 | + if (maj_stat == GSS_S_COMPLETE)
|
---|
1596 | + {
|
---|
1597 | + psocket->LogMessage(MessageType::Error, _T("GSSAPI Error Minor Status: %.*s"),
|
---|
1598 | + (int) status_string.length,
|
---|
1599 | + (char *) status_string.value);
|
---|
1600 | + p_gss_release_buffer(&min_stat, &status_string);
|
---|
1601 | + }
|
---|
1602 | + } while (message_context != 0);
|
---|
1603 | +}
|
---|
1604 | diff --git a/src/engine/gsssocket.cpp b/src/engine/gsssocket.cpp
|
---|
1605 | new file mode 100644
|
---|
1606 | index 0000000..938b194
|
---|
1607 | --- /dev/null
|
---|
1608 | +++ b/src/engine/gsssocket.cpp
|
---|
1609 | @@ -0,0 +1,300 @@
|
---|
1610 | +#include <filezilla.h>
|
---|
1611 | +#include "engineprivate.h"
|
---|
1612 | +#include "gsssocket.h"
|
---|
1613 | +#include "ControlSocket.h"
|
---|
1614 | +#include <errno.h>
|
---|
1615 | +
|
---|
1616 | +CGssSocket::CGssSocket(CEventHandler* pEvtHandler, CSocket* pSocket,
|
---|
1617 | + CControlSocket* pOwner, void *gcontext_in,
|
---|
1618 | + size_t pbufSize)
|
---|
1619 | + : CEventHandler(pOwner->event_loop_)
|
---|
1620 | + , CBackend(pEvtHandler)
|
---|
1621 | + , m_pOwner(pOwner)
|
---|
1622 | + , gcontext(gcontext_in)
|
---|
1623 | + , p_bufSize(pbufSize)
|
---|
1624 | + , databuffer(NULL)
|
---|
1625 | + , databuffersize(0)
|
---|
1626 | + , datainbuffer(0)
|
---|
1627 | + , encbuffer(NULL)
|
---|
1628 | + , encbuffersize(0)
|
---|
1629 | + , encbufferlen(0)
|
---|
1630 | + , llen(4)
|
---|
1631 | + , endoffile(false)
|
---|
1632 | + , writewait(false)
|
---|
1633 | + , shutdown(false)
|
---|
1634 | +{
|
---|
1635 | + wxASSERT(pSocket);
|
---|
1636 | +
|
---|
1637 | + m_pSocket = pSocket;
|
---|
1638 | + m_pSocketBackend = new CSocketBackend(this, *m_pSocket, m_pOwner->GetEngine().GetRateLimiter());
|
---|
1639 | + GssWrapSizeLimit(m_pOwner, gcontext, p_bufSize, &maxwrap);
|
---|
1640 | +}
|
---|
1641 | +
|
---|
1642 | +CGssSocket::~CGssSocket()
|
---|
1643 | +{
|
---|
1644 | + delete m_pSocketBackend;
|
---|
1645 | + if (databuffer)
|
---|
1646 | + free(databuffer);
|
---|
1647 | + if (encbuffer)
|
---|
1648 | + free(encbuffer);
|
---|
1649 | +}
|
---|
1650 | +
|
---|
1651 | +int
|
---|
1652 | +CGssSocket::Read(void *buffer, unsigned int size, int& error)
|
---|
1653 | +{
|
---|
1654 | + if (datainbuffer == 0 && !endoffile) {
|
---|
1655 | + if (!FetchData(error)) {
|
---|
1656 | + return -1;
|
---|
1657 | + }
|
---|
1658 | + }
|
---|
1659 | +
|
---|
1660 | + if (endoffile == true)
|
---|
1661 | + return 0;
|
---|
1662 | +
|
---|
1663 | + unsigned int retsize = datainbuffer > size ? size : datainbuffer;
|
---|
1664 | +
|
---|
1665 | + memcpy(buffer, dataptr, retsize);
|
---|
1666 | +
|
---|
1667 | + dataptr += retsize;
|
---|
1668 | + datainbuffer -= retsize;
|
---|
1669 | +
|
---|
1670 | + return retsize;
|
---|
1671 | +}
|
---|
1672 | +
|
---|
1673 | +/*
|
---|
1674 | + * Called to fill the buffer based on how much data we need
|
---|
1675 | + */
|
---|
1676 | +
|
---|
1677 | +bool CGssSocket::FetchData(int& error)
|
---|
1678 | +{
|
---|
1679 | + int cc;
|
---|
1680 | +
|
---|
1681 | + /*
|
---|
1682 | + * If llen > 0, then that means we need to read length bytes.
|
---|
1683 | + * If llen == 0, then that means we already have the length, it's
|
---|
1684 | + * in packetsize, and we can skip that.
|
---|
1685 | + */
|
---|
1686 | +
|
---|
1687 | + if (llen > 0) {
|
---|
1688 | +
|
---|
1689 | + /*
|
---|
1690 | + * According to RFC 2228, each packet is prefixed by 4
|
---|
1691 | + * bytes which contains the length of the data. We're
|
---|
1692 | + * just going to hardcode this as "4" right now.
|
---|
1693 | + */
|
---|
1694 | +
|
---|
1695 | + while (llen > 0) {
|
---|
1696 | + cc = m_pSocketBackend->Read(lenbytes + 4 - llen,
|
---|
1697 | + llen, error);
|
---|
1698 | +
|
---|
1699 | + if (cc == 0) {
|
---|
1700 | + error = ECONNABORTED;
|
---|
1701 | + return false;
|
---|
1702 | + }
|
---|
1703 | +
|
---|
1704 | + if (cc < 0) {
|
---|
1705 | + return false;
|
---|
1706 | + }
|
---|
1707 | +
|
---|
1708 | + llen -= cc;
|
---|
1709 | + }
|
---|
1710 | +
|
---|
1711 | + packetsize = (lenbytes[0] << 24) + (lenbytes[1] << 16) +
|
---|
1712 | + (lenbytes[2] << 8) + lenbytes[3];
|
---|
1713 | +
|
---|
1714 | + if (packetsize > encbuffersize) {
|
---|
1715 | + encbuffer = (unsigned char *) realloc(encbuffer,
|
---|
1716 | + packetsize);
|
---|
1717 | + encbuffersize = packetsize;
|
---|
1718 | + }
|
---|
1719 | +
|
---|
1720 | + encbufferlen = 0;
|
---|
1721 | + }
|
---|
1722 | +
|
---|
1723 | + while (encbufferlen < packetsize) {
|
---|
1724 | + cc = m_pSocketBackend->Read(encbuffer + encbufferlen,
|
---|
1725 | + packetsize - encbufferlen, error);
|
---|
1726 | + if (cc <= 0)
|
---|
1727 | + return false;
|
---|
1728 | +
|
---|
1729 | + encbufferlen += cc;
|
---|
1730 | + }
|
---|
1731 | +
|
---|
1732 | + /*
|
---|
1733 | + * Should be a full GSS packet of data now
|
---|
1734 | + */
|
---|
1735 | +
|
---|
1736 | + if (!GssUnwrap(m_pOwner, gcontext, encbuffer, packetsize, &databuffer,
|
---|
1737 | + &databuffersize, &datainbuffer)) {
|
---|
1738 | + error = EIO;
|
---|
1739 | + return false;
|
---|
1740 | + }
|
---|
1741 | +
|
---|
1742 | + dataptr = databuffer;
|
---|
1743 | + llen = 4;
|
---|
1744 | +
|
---|
1745 | + /*
|
---|
1746 | + * An EOF is encoded by a packet with no data
|
---|
1747 | + */
|
---|
1748 | +
|
---|
1749 | + if (datainbuffer == 0)
|
---|
1750 | + endoffile = true;
|
---|
1751 | +
|
---|
1752 | + return true;
|
---|
1753 | +}
|
---|
1754 | +
|
---|
1755 | +void CGssSocket::operator()(CEventBase const& ev)
|
---|
1756 | +{
|
---|
1757 | + Dispatch<CSocketEvent>(ev, this, &CGssSocket::OnSocketEvent);
|
---|
1758 | +}
|
---|
1759 | +
|
---|
1760 | +void CGssSocket::OnSocketEvent(CSocketEventSource*, SocketEventType t, int error)
|
---|
1761 | +{
|
---|
1762 | + switch (t)
|
---|
1763 | + {
|
---|
1764 | + case SocketEventType::read:
|
---|
1765 | + {
|
---|
1766 | + m_pEvtHandler->SendEvent<CSocketEvent>(this, SocketEventType::read, 0);
|
---|
1767 | + break;
|
---|
1768 | + }
|
---|
1769 | + case SocketEventType::write:
|
---|
1770 | + {
|
---|
1771 | + int ret = 0;
|
---|
1772 | +
|
---|
1773 | + if (writewait)
|
---|
1774 | + ret = PushData();
|
---|
1775 | +
|
---|
1776 | + if (ret == 0) {
|
---|
1777 | + m_pEvtHandler->SendEvent<CSocketEvent>(this, SocketEventType::write, 0);
|
---|
1778 | + }
|
---|
1779 | +
|
---|
1780 | + break;
|
---|
1781 | + }
|
---|
1782 | + default:
|
---|
1783 | + break;
|
---|
1784 | + }
|
---|
1785 | +}
|
---|
1786 | +
|
---|
1787 | +int CGssSocket::PushData(void)
|
---|
1788 | +{
|
---|
1789 | + int cc, error;
|
---|
1790 | +
|
---|
1791 | + if (!writewait)
|
---|
1792 | + return 0;
|
---|
1793 | +
|
---|
1794 | + while (datainbuffer > 0) {
|
---|
1795 | + cc = m_pSocketBackend->Write(dataptr, datainbuffer, error);
|
---|
1796 | +
|
---|
1797 | + if (cc < 0) {
|
---|
1798 | + if (error != EAGAIN)
|
---|
1799 | + endoffile = true;
|
---|
1800 | + return error;
|
---|
1801 | + }
|
---|
1802 | +
|
---|
1803 | + if (cc == 0) {
|
---|
1804 | + return EIO;
|
---|
1805 | + }
|
---|
1806 | +
|
---|
1807 | + dataptr += cc;
|
---|
1808 | + datainbuffer -= cc;
|
---|
1809 | + }
|
---|
1810 | +
|
---|
1811 | + if (datainbuffer == 0)
|
---|
1812 | + writewait = false;
|
---|
1813 | +
|
---|
1814 | + return 0;
|
---|
1815 | +}
|
---|
1816 | +
|
---|
1817 | +int CGssSocket::Write(const void *buffer, unsigned int len, int& error)
|
---|
1818 | +{
|
---|
1819 | + size_t bytestowrite;
|
---|
1820 | + int cc;
|
---|
1821 | +
|
---|
1822 | + if (endoffile) {
|
---|
1823 | + error = ENOTCONN;
|
---|
1824 | + return -1;
|
---|
1825 | + }
|
---|
1826 | +
|
---|
1827 | + if (writewait) {
|
---|
1828 | + error = EAGAIN;
|
---|
1829 | + return -1;
|
---|
1830 | + }
|
---|
1831 | +
|
---|
1832 | + bytestowrite = len > maxwrap ? maxwrap : len;
|
---|
1833 | +
|
---|
1834 | + if (!GssWrap(m_pOwner, gcontext, true, (unsigned char *) buffer,
|
---|
1835 | + bytestowrite, &databuffer, &databuffersize,
|
---|
1836 | + &datainbuffer, 4)) {
|
---|
1837 | + error = EIO;
|
---|
1838 | + return -1;
|
---|
1839 | + }
|
---|
1840 | +
|
---|
1841 | + /*
|
---|
1842 | + * Prefix the buffer with the length, and bump our length to include
|
---|
1843 | + * the buffer prefix.
|
---|
1844 | + */
|
---|
1845 | +
|
---|
1846 | + databuffer[0] = (datainbuffer >> 24) & 0xff;
|
---|
1847 | + databuffer[1] = (datainbuffer >> 16) & 0xff;
|
---|
1848 | + databuffer[2] = (datainbuffer >> 8) & 0xff;
|
---|
1849 | + databuffer[3] = datainbuffer & 0xff;
|
---|
1850 | +
|
---|
1851 | + datainbuffer += 4;
|
---|
1852 | +
|
---|
1853 | + dataptr = databuffer;
|
---|
1854 | +
|
---|
1855 | + while (datainbuffer > 0) {
|
---|
1856 | + cc = m_pSocketBackend->Write(dataptr, datainbuffer, error);
|
---|
1857 | +
|
---|
1858 | + if (cc <= 0) {
|
---|
1859 | + if (cc < 0 && error != EAGAIN)
|
---|
1860 | + return -1;
|
---|
1861 | + writewait = true;
|
---|
1862 | + break;
|
---|
1863 | + }
|
---|
1864 | +
|
---|
1865 | + dataptr += cc;
|
---|
1866 | + datainbuffer -= cc;
|
---|
1867 | + }
|
---|
1868 | +
|
---|
1869 | + /*
|
---|
1870 | + * If data is queued by us, we need to tell the upper layers that
|
---|
1871 | + * we've "written" it all, so we don't get it again. So always
|
---|
1872 | + * return bytestowrite at this point.
|
---|
1873 | + */
|
---|
1874 | +
|
---|
1875 | + return bytestowrite;
|
---|
1876 | +}
|
---|
1877 | +
|
---|
1878 | +int CGssSocket::Shutdown(void)
|
---|
1879 | +{
|
---|
1880 | + int error;
|
---|
1881 | +
|
---|
1882 | + if (shutdown && writewait)
|
---|
1883 | + return EAGAIN;
|
---|
1884 | +
|
---|
1885 | + /*
|
---|
1886 | + * At the end of our write, we should encode a GSS packet with
|
---|
1887 | + * a zero length.
|
---|
1888 | + */
|
---|
1889 | +
|
---|
1890 | + shutdown = true;
|
---|
1891 | +
|
---|
1892 | + if (Write(NULL, 0, error) < 0)
|
---|
1893 | + return error;
|
---|
1894 | +
|
---|
1895 | + return 0;
|
---|
1896 | +}
|
---|
1897 | +
|
---|
1898 | +/*
|
---|
1899 | + * All stubs for now
|
---|
1900 | + */
|
---|
1901 | +
|
---|
1902 | +void CGssSocket::OnRateAvailable(enum CRateLimiter::rate_direction)
|
---|
1903 | +{
|
---|
1904 | +}
|
---|
1905 | +
|
---|
1906 | +int CGssSocket::Peek(void *buffer, unsigned int len, int& error)
|
---|
1907 | +{
|
---|
1908 | + return 0;
|
---|
1909 | +}
|
---|
1910 | diff --git a/src/engine/gsssocket.h b/src/engine/gsssocket.h
|
---|
1911 | new file mode 100644
|
---|
1912 | index 0000000..2017724
|
---|
1913 | --- /dev/null
|
---|
1914 | +++ b/src/engine/gsssocket.h
|
---|
1915 | @@ -0,0 +1,53 @@
|
---|
1916 | +#ifndef __GSSSOCKET_H__
|
---|
1917 | +#define __GSSSOCKET_H__
|
---|
1918 | +
|
---|
1919 | +#include "gssinterface.h"
|
---|
1920 | +#include "backend.h"
|
---|
1921 | +#include "socket.h"
|
---|
1922 | +
|
---|
1923 | +class CControlSocket;
|
---|
1924 | +class CGssSocket : protected CEventHandler, public CBackend
|
---|
1925 | +{
|
---|
1926 | +public:
|
---|
1927 | + CGssSocket(CEventHandler *pEvtHandler, CSocket *psocket,
|
---|
1928 | + CControlSocket *pOwner, void *gcontext_in, size_t pbsz);
|
---|
1929 | + virtual ~CGssSocket();
|
---|
1930 | +
|
---|
1931 | + virtual int Read(void *buffer, unsigned int size, int& error);
|
---|
1932 | + virtual int Peek(void *buffer, unsigned int size, int& error);
|
---|
1933 | + virtual int Write(const void *buffer, unsigned int size, int& error);
|
---|
1934 | + virtual int Shutdown(void);
|
---|
1935 | +
|
---|
1936 | +protected:
|
---|
1937 | + bool FetchData(int& error);
|
---|
1938 | + int PushData(void);
|
---|
1939 | + void OnSocketEvent(CSocketEventSource*, SocketEventType, int);
|
---|
1940 | + virtual void OnRateAvailable(enum CRateLimiter::rate_direction direction);
|
---|
1941 | + virtual void operator()(CEventBase const& ev);
|
---|
1942 | +
|
---|
1943 | + CSocketBackend* m_pSocketBackend;
|
---|
1944 | + CControlSocket* m_pOwner;
|
---|
1945 | + CSocket* m_pSocket;
|
---|
1946 | + void *gcontext;
|
---|
1947 | + size_t p_bufSize; /* PBSZ from connection */
|
---|
1948 | + size_t maxwrap; /* Max size of data to gss_wrap */
|
---|
1949 | +
|
---|
1950 | + /*
|
---|
1951 | + * We use "databuffer" to hold network data for reading and writing
|
---|
1952 | + */
|
---|
1953 | +
|
---|
1954 | + unsigned char *databuffer; /* Decrypted data buffer */
|
---|
1955 | + unsigned char *dataptr; /* Ptr to next data to be read */
|
---|
1956 | + size_t databuffersize; /* Size of databuffer */
|
---|
1957 | + size_t datainbuffer; /* # of bytes in databuffer */
|
---|
1958 | + unsigned int packetsize; /* Size of encrypted packet */
|
---|
1959 | + unsigned char *encbuffer; /* Encrypted buffer */
|
---|
1960 | + size_t encbuffersize; /* Size of encrypted buffer */
|
---|
1961 | + size_t encbufferlen; /* # of bytes in encrypted buffer */
|
---|
1962 | + unsigned char lenbytes[4]; /* Buffer for length bytes */
|
---|
1963 | + unsigned int llen; /* Remaining bytes to fill lenbytes */
|
---|
1964 | + bool endoffile; /* Set to true if the net is closed */
|
---|
1965 | + bool writewait; /* True if waiting to write */
|
---|
1966 | + bool shutdown; /* True if shutting down */
|
---|
1967 | +};
|
---|
1968 | +#endif /* __GSSSOCKET_H__ */
|
---|
1969 | diff --git a/src/engine/transfersocket.cpp b/src/engine/transfersocket.cpp
|
---|
1970 | index 65d79e6..af08d3d 100644
|
---|
1971 | --- a/src/engine/transfersocket.cpp
|
---|
1972 | +++ b/src/engine/transfersocket.cpp
|
---|
1973 | @@ -5,6 +5,7 @@
|
---|
1974 | #include "iothread.h"
|
---|
1975 | #include "optionsbase.h"
|
---|
1976 | #include "tlssocket.h"
|
---|
1977 | +#include "gsssocket.h"
|
---|
1978 | #include "transfersocket.h"
|
---|
1979 | #include "proxy.h"
|
---|
1980 | #include "servercapabilities.h"
|
---|
1981 | @@ -39,12 +40,17 @@ void CTransferSocket::ResetSocket()
|
---|
1982 | if( m_pBackend == m_pTlsSocket ) {
|
---|
1983 | m_pBackend = 0;
|
---|
1984 | }
|
---|
1985 | + if (m_pBackend == m_pGssSocket) {
|
---|
1986 | + m_pBackend = 0;
|
---|
1987 | + }
|
---|
1988 | delete m_pTlsSocket;
|
---|
1989 | + delete m_pGssSocket;
|
---|
1990 | delete m_pBackend;
|
---|
1991 | delete m_pSocketServer;
|
---|
1992 | delete m_pSocket;
|
---|
1993 | m_pProxyBackend = 0;
|
---|
1994 | m_pTlsSocket = 0;
|
---|
1995 | + m_pGssSocket = 0;
|
---|
1996 | m_pBackend = 0;
|
---|
1997 | m_pSocketServer = 0;
|
---|
1998 | m_pSocket = 0;
|
---|
1999 | @@ -430,6 +436,13 @@ void CTransferSocket::OnClose(int error)
|
---|
2000 | else
|
---|
2001 | TransferEnd(TransferEndReason::successful);
|
---|
2002 | }
|
---|
2003 | + else if (m_shutdown && m_pGssSocket)
|
---|
2004 | + {
|
---|
2005 | + if (m_pGssSocket->Shutdown() != 0)
|
---|
2006 | + TransferEnd(TransferEndReason::transfer_failure);
|
---|
2007 | + else
|
---|
2008 | + TransferEnd(TransferEndReason::successful);
|
---|
2009 | + }
|
---|
2010 | else
|
---|
2011 | TransferEnd(TransferEndReason::transfer_failure);
|
---|
2012 | return;
|
---|
2013 | @@ -637,10 +650,12 @@ bool CTransferSocket::CheckGetNextReadBuffer()
|
---|
2014 | return false;
|
---|
2015 | }
|
---|
2016 | else if (res == IO_Success) {
|
---|
2017 | - if (m_pTlsSocket) {
|
---|
2018 | + if (m_pTlsSocket || m_pGssSocket) {
|
---|
2019 | m_shutdown = true;
|
---|
2020 |
|
---|
2021 | - int error = m_pTlsSocket->Shutdown();
|
---|
2022 | + int error = m_pTlsSocket ?
|
---|
2023 | + m_pTlsSocket->Shutdown() :
|
---|
2024 | + m_pGssSocket->Shutdown();
|
---|
2025 | if (error != 0) {
|
---|
2026 | if (error != EAGAIN)
|
---|
2027 | TransferEnd(TransferEndReason::transfer_failure);
|
---|
2028 | @@ -714,6 +729,16 @@ bool CTransferSocket::InitTls(const CTlsSocket* pPrimaryTlsSocket)
|
---|
2029 | return true;
|
---|
2030 | }
|
---|
2031 |
|
---|
2032 | +bool CTransferSocket::InitGss()
|
---|
2033 | +{
|
---|
2034 | + m_pGssSocket = new CGssSocket(this, m_pSocket, &controlSocket_,
|
---|
2035 | + controlSocket_.gcontext,
|
---|
2036 | + controlSocket_.m_protBufferSize);
|
---|
2037 | +
|
---|
2038 | + m_pBackend = m_pGssSocket;
|
---|
2039 | + return true;
|
---|
2040 | +}
|
---|
2041 | +
|
---|
2042 | void CTransferSocket::TriggerPostponedEvents()
|
---|
2043 | {
|
---|
2044 | wxASSERT(m_bActive);
|
---|
2045 | @@ -742,7 +767,13 @@ bool CTransferSocket::InitBackend()
|
---|
2046 | return true;
|
---|
2047 |
|
---|
2048 | if (controlSocket_.m_protectDataChannel) {
|
---|
2049 | - if (!InitTls(controlSocket_.m_pTlsSocket))
|
---|
2050 | + bool ret;
|
---|
2051 | + if (controlSocket_.gcontext) {
|
---|
2052 | + ret = InitGss();
|
---|
2053 | + } else {
|
---|
2054 | + ret = InitTls(controlSocket_.m_pTlsSocket);
|
---|
2055 | + }
|
---|
2056 | + if (!ret)
|
---|
2057 | return false;
|
---|
2058 | }
|
---|
2059 | else
|
---|
2060 | diff --git a/src/engine/transfersocket.h b/src/engine/transfersocket.h
|
---|
2061 | index ec537c7..46e49d5 100644
|
---|
2062 | --- a/src/engine/transfersocket.h
|
---|
2063 | +++ b/src/engine/transfersocket.h
|
---|
2064 | @@ -19,6 +19,7 @@ enum class TransferMode
|
---|
2065 |
|
---|
2066 | class CIOThread;
|
---|
2067 | class CTlsSocket;
|
---|
2068 | +class CGssSocket;
|
---|
2069 | class CTransferSocket final : public CEventHandler
|
---|
2070 | {
|
---|
2071 | public:
|
---|
2072 | @@ -47,6 +48,7 @@ protected:
|
---|
2073 |
|
---|
2074 | bool InitBackend();
|
---|
2075 | bool InitTls(const CTlsSocket* pPrimaryTlsSocket);
|
---|
2076 | + bool InitGss();
|
---|
2077 |
|
---|
2078 | void ResetSocket();
|
---|
2079 |
|
---|
2080 | @@ -98,6 +100,8 @@ protected:
|
---|
2081 | CTlsSocket* m_pTlsSocket{};
|
---|
2082 | bool m_shutdown{};
|
---|
2083 |
|
---|
2084 | + CGssSocket* m_pGssSocket{};
|
---|
2085 | +
|
---|
2086 | // Needed for the madeProgress field in CTransferStatus
|
---|
2087 | // Initially 0, 2 if made progress
|
---|
2088 | // On uploads, 1 after first WSAE_WOULDBLOCK
|
---|
2089 | diff --git a/src/include/Makefile.am b/src/include/Makefile.am
|
---|
2090 | index 60a3e46..8fad5a3 100644
|
---|
2091 | --- a/src/include/Makefile.am
|
---|
2092 | +++ b/src/include/Makefile.am
|
---|
2093 | @@ -10,6 +10,7 @@ noinst_HEADERS = \
|
---|
2094 | event_loop.h \
|
---|
2095 | externalipresolver.h \
|
---|
2096 | FileZillaEngine.h \
|
---|
2097 | + gssinterface.h \
|
---|
2098 | libfilezilla.h \
|
---|
2099 | local_filesys.h \
|
---|
2100 | local_path.h \
|
---|
2101 | diff --git a/src/include/gssinterface.h b/src/include/gssinterface.h
|
---|
2102 | new file mode 100644
|
---|
2103 | index 0000000..c90bc0c
|
---|
2104 | --- /dev/null
|
---|
2105 | +++ b/src/include/gssinterface.h
|
---|
2106 | @@ -0,0 +1,142 @@
|
---|
2107 | +#ifndef __GSSINTERFACE_H__
|
---|
2108 | +#define __GSSINTERFACE_H__
|
---|
2109 | +
|
---|
2110 | +class CControlSocket;
|
---|
2111 | +
|
---|
2112 | +/*
|
---|
2113 | + * Return 'true' if the GSSAPI library has loaded successfully. Will
|
---|
2114 | + * attempt to load it if it is not already loaded.
|
---|
2115 | + */
|
---|
2116 | +
|
---|
2117 | +bool IsGssLoaded(void);
|
---|
2118 | +
|
---|
2119 | +/*
|
---|
2120 | + * Load the GSS Library. If one is currently loaded, unload the old library
|
---|
2121 | + * first. Returns 'true' if load was successful, 'false' if not.
|
---|
2122 | + */
|
---|
2123 | +
|
---|
2124 | +bool LoadGssLibrary(const wxString &);
|
---|
2125 | +
|
---|
2126 | +/*
|
---|
2127 | + * Return the name of the currently configured GSS library
|
---|
2128 | + */
|
---|
2129 | +
|
---|
2130 | +wxString GetGssLibraryName(void);
|
---|
2131 | +
|
---|
2132 | +/*
|
---|
2133 | + * Return the last error we got when we tried to load the module
|
---|
2134 | + */
|
---|
2135 | +
|
---|
2136 | +wxString GetGssLoadError(void);
|
---|
2137 | +
|
---|
2138 | +/*
|
---|
2139 | + * Import a name via gss_import_name(). Takes target name (service@host)
|
---|
2140 | + * as input, returns a gss_name_t. Returns false on failure.
|
---|
2141 | + */
|
---|
2142 | +
|
---|
2143 | +bool GssImportName(CControlSocket *psocket, const wxString& , void **);
|
---|
2144 | +
|
---|
2145 | +/*
|
---|
2146 | + * Call gss_init_sec_context. Arguments are:
|
---|
2147 | + *
|
---|
2148 | + * psocket - Connection control socket (for logging)
|
---|
2149 | + * context - Returned/modified gss_ctx_id_t. Should be NULL at first
|
---|
2150 | + * call.
|
---|
2151 | + * name - Target name (from gss_import_name)
|
---|
2152 | + * delegate - if 'true', delegate credentials
|
---|
2153 | + * input_token - Base64-encoded input token
|
---|
2154 | + * output_token - Base64-encoded output token
|
---|
2155 | + * complete - Return 'true' if function returned GSS_S_COMPLETE
|
---|
2156 | + *
|
---|
2157 | + * Returns false on failure.
|
---|
2158 | + */
|
---|
2159 | +
|
---|
2160 | +bool GssInitSecContext(CControlSocket* psocket, void **context,
|
---|
2161 | + void *name, bool delegate, const wxString &input_token,
|
---|
2162 | + wxString *output_token, bool *complete);
|
---|
2163 | +
|
---|
2164 | +/*
|
---|
2165 | + * Call gss_wrap on data to perform encryption/integrity protection.
|
---|
2166 | + * Arguments are:
|
---|
2167 | + *
|
---|
2168 | + * psocket - Connection control socket (for logging)
|
---|
2169 | + * context - gss_ctx_id_t from gss_init_sec_context.
|
---|
2170 | + * encrypt - set to 'true' if performing encryption.
|
---|
2171 | + * inbuf - Input data
|
---|
2172 | + * outbuf - Base64-encoded output data
|
---|
2173 | + *
|
---|
2174 | + * Returns false on failure.
|
---|
2175 | + */
|
---|
2176 | +
|
---|
2177 | +bool GssWrap(CControlSocket* psocket, void *context, bool encrypt,
|
---|
2178 | + const wxCharBuffer& inbuf, wxString *outbuf);
|
---|
2179 | +
|
---|
2180 | +/*
|
---|
2181 | + * Alternate version of GssWrap that does not perform any base64 encoding
|
---|
2182 | + *
|
---|
2183 | + * Similar arguments as above, except that outbuf can be reallocated if
|
---|
2184 | + * it is not big enough (buffer size is passed in via *outbufsize).
|
---|
2185 | + *
|
---|
2186 | + * Offset is a "buffer offset" in case you need to do something like prepend
|
---|
2187 | + * length
|
---|
2188 | + */
|
---|
2189 | +
|
---|
2190 | +bool GssWrap(CControlSocket* psocket, void *context, bool encrypt,
|
---|
2191 | + const unsigned char *inbuf, size_t inbuflen,
|
---|
2192 | + unsigned char **outbuf, size_t *outbufsize, size_t *outbuflen,
|
---|
2193 | + size_t offset);
|
---|
2194 | +
|
---|
2195 | +/*
|
---|
2196 | + * Call gss_unwrap on data to perform decryption/integrity verification.
|
---|
2197 | + * Arguments are:
|
---|
2198 | + *
|
---|
2199 | + * psocket - Connection control socket (for logging)
|
---|
2200 | + * context - gss_ctx_id_t from gss_init_sec_context.
|
---|
2201 | + * inbuf - Base64-encoded input data
|
---|
2202 | + * outbuf - Output data
|
---|
2203 | + * encrypted - Will be set to 'true' if data was encrypted
|
---|
2204 | + *
|
---|
2205 | + * Returns false on failure.
|
---|
2206 | + */
|
---|
2207 | +
|
---|
2208 | +bool GssUnwrap(CControlSocket* psocket, void *context, const wxString& inbuf,
|
---|
2209 | + wxMemoryBuffer *outbuf, bool *encrypted);
|
---|
2210 | +
|
---|
2211 | +/*
|
---|
2212 | + * Alternate version of gss_unwrap which does not perform base64 decoding.
|
---|
2213 | + *
|
---|
2214 | + * Similar arguments to above function, except outbuf can be reallocated
|
---|
2215 | + * if size isn't big enough.
|
---|
2216 | + */
|
---|
2217 | +
|
---|
2218 | +bool GssUnwrap(CControlSocket* psocket, void *context, unsigned char *inbuf,
|
---|
2219 | + size_t inbuflen, unsigned char **outbuf, size_t *outbuflen,
|
---|
2220 | + size_t *retbufsize);
|
---|
2221 | +
|
---|
2222 | +/*
|
---|
2223 | + * Call gss_release_name to release a name buffer
|
---|
2224 | + * Arguments are:
|
---|
2225 | + *
|
---|
2226 | + * psocket - Connection control socket (for logging)
|
---|
2227 | + * name - Pointer to name buffer to release
|
---|
2228 | + *
|
---|
2229 | + */
|
---|
2230 | +
|
---|
2231 | +void GssReleaseName(CControlSocket* psocket, void **name);
|
---|
2232 | +
|
---|
2233 | +/*
|
---|
2234 | + * Call gss_wrap_size_limit to determine the maximum amount of unencrypted
|
---|
2235 | + * data we can send given an encrypted buffer size.
|
---|
2236 | + * Arguments are:
|
---|
2237 | +
|
---|
2238 | + * psocket - Connection control socket (for logging)
|
---|
2239 | + * context - gss_ctx_id_t from gss_init_sec_context.
|
---|
2240 | + * output_size - Requested output size
|
---|
2241 | + * max_input_size - Maximum input size
|
---|
2242 | + *
|
---|
2243 | + * Returns false on failure.
|
---|
2244 | + */
|
---|
2245 | +
|
---|
2246 | +bool GssWrapSizeLimit(CControlSocket* psocket, void *context,
|
---|
2247 | + size_t output_size, size_t *max_input_size);
|
---|
2248 | +#endif /* __GSSINTERFACE_H__ */
|
---|
2249 | diff --git a/src/include/option_change_event_handler.h b/src/include/option_change_event_handler.h
|
---|
2250 | index 3ebb6fd..37734c7 100644
|
---|
2251 | --- a/src/include/option_change_event_handler.h
|
---|
2252 | +++ b/src/include/option_change_event_handler.h
|
---|
2253 | @@ -8,7 +8,7 @@
|
---|
2254 | class COptions;
|
---|
2255 |
|
---|
2256 | enum {
|
---|
2257 | - changed_options_size = 128
|
---|
2258 | + changed_options_size = 256
|
---|
2259 | };
|
---|
2260 |
|
---|
2261 | typedef std::bitset<changed_options_size> changed_options_t;
|
---|
2262 | diff --git a/src/include/optionsbase.h b/src/include/optionsbase.h
|
---|
2263 | index 8b3266d..9e668f4 100644
|
---|
2264 | --- a/src/include/optionsbase.h
|
---|
2265 | +++ b/src/include/optionsbase.h
|
---|
2266 | @@ -33,6 +33,11 @@ enum engineOptions
|
---|
2267 |
|
---|
2268 | OPTION_ALLOW_TRANSFERMODEFALLBACK, // If PORT fails, allow PASV and vice versa
|
---|
2269 |
|
---|
2270 | + OPTION_GSS_ENABLE,
|
---|
2271 | + OPTION_GSS_LIBRARY,
|
---|
2272 | + OPTION_GSS_ENCRYPTDATACHAN,
|
---|
2273 | + OPTION_GSS_PROTBUFSIZE,
|
---|
2274 | +
|
---|
2275 | OPTION_RECONNECTCOUNT,
|
---|
2276 | OPTION_RECONNECTDELAY,
|
---|
2277 |
|
---|
2278 | diff --git a/src/interface/Makefile.am b/src/interface/Makefile.am
|
---|
2279 | index 91b2f00..94e7e9b 100644
|
---|
2280 | --- a/src/interface/Makefile.am
|
---|
2281 | +++ b/src/interface/Makefile.am
|
---|
2282 | @@ -80,6 +80,7 @@ filezilla_SOURCES = aboutdialog.cpp \
|
---|
2283 | settings/optionspage_filelists.cpp \
|
---|
2284 | settings/optionspage_filetype.cpp \
|
---|
2285 | settings/optionspage_ftpproxy.cpp \
|
---|
2286 | + settings/optionspage_gssauth.cpp \
|
---|
2287 | settings/optionspage_interface.cpp \
|
---|
2288 | settings/optionspage_language.cpp \
|
---|
2289 | settings/optionspage_logging.cpp \
|
---|
2290 | diff --git a/src/interface/Options.cpp b/src/interface/Options.cpp
|
---|
2291 | index f718614..b75acdb 100644
|
---|
2292 | --- a/src/interface/Options.cpp
|
---|
2293 | +++ b/src/interface/Options.cpp
|
---|
2294 | @@ -76,6 +76,10 @@ static const t_Option options[OPTIONS_NUM] =
|
---|
2295 | { "Logging Raw Listing", number, _T("0"), normal },
|
---|
2296 | { "fzsftp executable", string, _T(""), internal },
|
---|
2297 | { "Allow transfermode fallback", number, _T("1"), normal },
|
---|
2298 | + { "Enable GSSAPI Authentication", number, _T("1"), normal },
|
---|
2299 | + { "GSSAPI library name", string, _T(""), normal },
|
---|
2300 | + { "GSSAPI data channel encrypt", number, _T("0"), normal },
|
---|
2301 | + { "GSSAPI protection buffer size", number, _T("65536"), normal },
|
---|
2302 | { "Reconnect count", number, _T("2"), normal },
|
---|
2303 | { "Reconnect delay", number, _T("5"), normal },
|
---|
2304 | { "Enable speed limits", number, _T("0"), normal },
|
---|
2305 | diff --git a/src/interface/resources/xrc/settings.xrc b/src/interface/resources/xrc/settings.xrc
|
---|
2306 | index c4b9af6..f5b116e 100644
|
---|
2307 | --- a/src/interface/resources/xrc/settings.xrc
|
---|
2308 | +++ b/src/interface/resources/xrc/settings.xrc
|
---|
2309 | @@ -607,6 +607,109 @@
|
---|
2310 | </object>
|
---|
2311 | </object>
|
---|
2312 | </object>
|
---|
2313 | + <object class="wxPanel" name="ID_SETTINGS_CONNECTION_FTP_GSSAPI">
|
---|
2314 | + <object class="wxBoxSizer">
|
---|
2315 | + <orient>wxVERTICAL</orient>
|
---|
2316 | + <object class="sizeritem">
|
---|
2317 | + <object class="wxStaticBoxSizer">
|
---|
2318 | + <label>GSSAPI Authentication</label>
|
---|
2319 | + <orient>wxVERTICAL</orient>
|
---|
2320 | + <object class="sizeritem">
|
---|
2321 | + <flag>wxGROW</flag>
|
---|
2322 | + <object class="wxFlexGridSizer">
|
---|
2323 | + <orient>wxVERTICAL</orient>
|
---|
2324 | + <cols>1</cols>
|
---|
2325 | + <vgap>5</vgap>
|
---|
2326 | + <growablecols>0</growablecols>
|
---|
2327 | + <object class="sizeritem">
|
---|
2328 | + <object class="wxCheckBox" name="ID_ENABLEGSSAPI">
|
---|
2329 | + <label>Enable GSSAPI Authentication</label>
|
---|
2330 | + </object>
|
---|
2331 | + </object>
|
---|
2332 | + <object class="sizeritem">
|
---|
2333 | + <flag>wxGROW</flag>
|
---|
2334 | + <object class="wxBoxSizer">
|
---|
2335 | + <orient>wxHORIZONTAL</orient>
|
---|
2336 | + <hgap>3</hgap>
|
---|
2337 | + <object class="sizeritem">
|
---|
2338 | + <object class="wxStaticText">
|
---|
2339 | + <label>GSSAPI Plugin:</label>
|
---|
2340 | + </object>
|
---|
2341 | + <flag>wxALIGN_CENTER_VERTICAL</flag>
|
---|
2342 | + </object>
|
---|
2343 | + <object class="sizeritem">
|
---|
2344 | + <object class="wxTextCtrl" name="ID_GSSPLUGINNAME"/>
|
---|
2345 | + <flag>wxALIGN_CENTRE_VERTICAL|wxGROW</flag>
|
---|
2346 | + <option>1</option>
|
---|
2347 | + </object>
|
---|
2348 | + <object class="sizeritem">
|
---|
2349 | + <object class="wxButton" name="ID_BROWSEGSSPLUGIN">
|
---|
2350 | + <label>&Browse...</label>
|
---|
2351 | + </object>
|
---|
2352 | + <flag>wxALIGN_CENTRE_VERTICAL</flag>
|
---|
2353 | + </object>
|
---|
2354 | + <flag>wxGROW</flag>
|
---|
2355 | + </object>
|
---|
2356 | + </object>
|
---|
2357 | + <object class="sizeritem">
|
---|
2358 | + <flag>wxGROW</flag>
|
---|
2359 | + <object class="wxBoxSizer">
|
---|
2360 | + <orient>wxHORIZONTAL</orient>
|
---|
2361 | + <object class="sizeritem">
|
---|
2362 | + <object class="wxStaticText">
|
---|
2363 | + <label>Module status:</label>
|
---|
2364 | + </object>
|
---|
2365 | + </object>
|
---|
2366 | + <object class="sizeritem">
|
---|
2367 | + <flag>wxGROW</flag>
|
---|
2368 | + <option>1</option>
|
---|
2369 | + <object class="wxStaticText" name="ID_GSSMODSTATUS"/>
|
---|
2370 | + </object>
|
---|
2371 | + </object>
|
---|
2372 | + </object>
|
---|
2373 | + <object class="sizeritem">
|
---|
2374 | + <object class="wxStaticText">
|
---|
2375 | + <label>Note: the following settings only apply to new connections, not existing ones</label>
|
---|
2376 | + </object>
|
---|
2377 | + </object>
|
---|
2378 | + <object class="sizeritem">
|
---|
2379 | + <object class="wxCheckBox" name="ID_ENABLEGSSDATAENCRYPT">
|
---|
2380 | + <label>Enable Data Channel Encryption</label>
|
---|
2381 | + </object>
|
---|
2382 | + </object>
|
---|
2383 | + <object class="sizeritem">
|
---|
2384 | + <object class="wxFlexGridSizer">
|
---|
2385 | + <cols>3</cols>
|
---|
2386 | + <object class="sizeritem">
|
---|
2387 | + <object class="wxStaticText">
|
---|
2388 | + <label>Encrypted buffer size:</label>
|
---|
2389 | + </object>
|
---|
2390 | + <flag>wxALIGN_CENTRE_VERTICAL</flag>
|
---|
2391 | + </object>
|
---|
2392 | + <object class="sizeritem">
|
---|
2393 | + <object class="wxTextCtrl" name="ID_GSSPROTBUFSIZE">
|
---|
2394 | + <size>34,-1d</size>
|
---|
2395 | + </object>
|
---|
2396 | + <flag>wxALIGN_CENTRE_VERTICAL</flag>
|
---|
2397 | + </object>
|
---|
2398 | + <hgap>4</hgap>
|
---|
2399 | + <object class="sizeritem">
|
---|
2400 | + <object class="wxStaticText">
|
---|
2401 | + <label>(32768-1048576)</label>
|
---|
2402 | + </object>
|
---|
2403 | + <flag>wxALIGN_CENTRE_VERTICAL</flag>
|
---|
2404 | + </object>
|
---|
2405 | + </object>
|
---|
2406 | + </object>
|
---|
2407 | + </object>
|
---|
2408 | + <flag>wxLEFT|wxRIGHT|wxBOTTOM</flag>
|
---|
2409 | + <border>4</border>
|
---|
2410 | + </object>
|
---|
2411 | + </object>
|
---|
2412 | + <flag>wxGROW</flag>
|
---|
2413 | + </object>
|
---|
2414 | + </object>
|
---|
2415 | + </object>
|
---|
2416 | <object class="wxPanel" name="ID_SETTINGS_CONNECTION_SFTP">
|
---|
2417 | <object class="wxFlexGridSizer">
|
---|
2418 | <cols>2</cols>
|
---|
2419 | diff --git a/src/interface/settings/optionspage_gssauth.cpp b/src/interface/settings/optionspage_gssauth.cpp
|
---|
2420 | new file mode 100644
|
---|
2421 | index 0000000..9f96e5f
|
---|
2422 | --- /dev/null
|
---|
2423 | +++ b/src/interface/settings/optionspage_gssauth.cpp
|
---|
2424 | @@ -0,0 +1,129 @@
|
---|
2425 | +#include <filezilla.h>
|
---|
2426 | +
|
---|
2427 | +#include "../Options.h"
|
---|
2428 | +#include "settingsdialog.h"
|
---|
2429 | +#include "optionspage.h"
|
---|
2430 | +#include "optionspage_gssauth.h"
|
---|
2431 | +#include "gssinterface.h"
|
---|
2432 | +
|
---|
2433 | +BEGIN_EVENT_TABLE(COptionsPageGssAuth, COptionsPageGssAuth::COptionsPage)
|
---|
2434 | +EVT_CHECKBOX(XRCID("ID_ENABLEGSSAPI"), COptionsPageGssAuth::OnGssSettingChanged)
|
---|
2435 | +EVT_CHECKBOX(XRCID("ID_ENABLEGSSDATAENCRYPT"), COptionsPageGssAuth::OnGssSettingChanged)
|
---|
2436 | +EVT_BUTTON(XRCID("ID_BROWSEGSSPLUGIN"), COptionsPageGssAuth::OnBrowse)
|
---|
2437 | +END_EVENT_TABLE()
|
---|
2438 | +
|
---|
2439 | +bool COptionsPageGssAuth::LoadPage()
|
---|
2440 | +{
|
---|
2441 | + bool failure = false;
|
---|
2442 | + wxString libname;
|
---|
2443 | +
|
---|
2444 | + SetCheckFromOption(XRCID("ID_ENABLEGSSAPI"), OPTION_GSS_ENABLE,
|
---|
2445 | + failure);
|
---|
2446 | +
|
---|
2447 | + libname = m_pOptions->GetOption(OPTION_GSS_LIBRARY);
|
---|
2448 | +
|
---|
2449 | + if (libname.IsEmpty()) {
|
---|
2450 | + libname = GetGssLibraryName();
|
---|
2451 | + }
|
---|
2452 | +
|
---|
2453 | + SetText(XRCID("ID_GSSPLUGINNAME"), libname, failure);
|
---|
2454 | +
|
---|
2455 | + SetCheckFromOption(XRCID("ID_ENABLEGSSDATAENCRYPT"),
|
---|
2456 | + OPTION_GSS_ENCRYPTDATACHAN, failure);
|
---|
2457 | +
|
---|
2458 | + SetTextFromOption(XRCID("ID_GSSPROTBUFSIZE"), OPTION_GSS_PROTBUFSIZE,
|
---|
2459 | + failure);
|
---|
2460 | +
|
---|
2461 | + if (!failure)
|
---|
2462 | + SetCtrlState();
|
---|
2463 | +
|
---|
2464 | + return !failure;
|
---|
2465 | +}
|
---|
2466 | +
|
---|
2467 | +bool COptionsPageGssAuth::SavePage()
|
---|
2468 | +{
|
---|
2469 | + SetOptionFromCheck(XRCID("ID_ENABLEGSSAPI"), OPTION_GSS_ENABLE);
|
---|
2470 | + SetOptionFromText(XRCID("ID_GSSPLUGINNAME"), OPTION_GSS_LIBRARY);
|
---|
2471 | + SetOptionFromCheck(XRCID("ID_ENABLEGSSDATAENCRYPT"),
|
---|
2472 | + OPTION_GSS_ENCRYPTDATACHAN);
|
---|
2473 | + SetOptionFromText(XRCID("ID_GSSPROTBUFSIZE"), OPTION_GSS_PROTBUFSIZE);
|
---|
2474 | +
|
---|
2475 | + return true;
|
---|
2476 | +}
|
---|
2477 | +
|
---|
2478 | +bool COptionsPageGssAuth::Validate()
|
---|
2479 | +{
|
---|
2480 | + wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_GSSPLUGINNAME", wxTextCtrl);
|
---|
2481 | +
|
---|
2482 | + if (pTextCtrl->IsModified()) {
|
---|
2483 | + pTextCtrl->SetModified(false);
|
---|
2484 | + LoadGssLibrary(pTextCtrl->GetValue());
|
---|
2485 | + }
|
---|
2486 | +
|
---|
2487 | + wxTextCtrl *pProtBufSz = XRCCTRL(*this, "ID_GSSPROTBUFSIZE", wxTextCtrl);
|
---|
2488 | +
|
---|
2489 | + long protbufsz;
|
---|
2490 | +
|
---|
2491 | + if (!pProtBufSz->GetValue().ToLong(&protbufsz) ||
|
---|
2492 | + protbufsz < 32768 || protbufsz > 1048576)
|
---|
2493 | + return DisplayError(pProtBufSz, _("Encryption buffer size must be between 32768 and 1048576."));
|
---|
2494 | +
|
---|
2495 | + return true;
|
---|
2496 | +}
|
---|
2497 | +
|
---|
2498 | +void COptionsPageGssAuth::OnBrowse(wxCommandEvent& event)
|
---|
2499 | +{
|
---|
2500 | + wxFileDialog dlg(this, _("Select GSS library"), wxString(),
|
---|
2501 | + GetGssLibraryName(),
|
---|
2502 | +#ifdef __WXMSW__
|
---|
2503 | + _T("Dynamic link library (*.dll)|*.dll"),
|
---|
2504 | +#elif __WXMAC__
|
---|
2505 | + _T("Shared library (*.dylib)|*.dylib;public.unix-executable"),
|
---|
2506 | +#else
|
---|
2507 | + wxFileSelectorDefaultWildcardStr,
|
---|
2508 | +#endif
|
---|
2509 | + wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
---|
2510 | +
|
---|
2511 | + if (dlg.ShowModal() != wxID_OK)
|
---|
2512 | + return;
|
---|
2513 | +
|
---|
2514 | + XRCCTRL(*this, "ID_GSSPLUGINNAME", wxTextCtrl)->ChangeValue(dlg.GetPath());
|
---|
2515 | +
|
---|
2516 | + XRCCTRL(*this, "ID_GSSPLUGINNAME", wxTextCtrl)->SetModified(true);
|
---|
2517 | +
|
---|
2518 | + SetCtrlState();
|
---|
2519 | +}
|
---|
2520 | +
|
---|
2521 | +void COptionsPageGssAuth::OnGssSettingChanged(wxCommandEvent& event)
|
---|
2522 | +{
|
---|
2523 | + SetCtrlState();
|
---|
2524 | +}
|
---|
2525 | +
|
---|
2526 | +void COptionsPageGssAuth::SetCtrlState()
|
---|
2527 | +{
|
---|
2528 | + bool enabled = XRCCTRL(*this, "ID_ENABLEGSSAPI", wxCheckBox)->GetValue();
|
---|
2529 | + wxTextCtrl *pTextCtrl = XRCCTRL(*this, "ID_GSSPLUGINNAME", wxTextCtrl);
|
---|
2530 | + pTextCtrl->Enable(enabled);
|
---|
2531 | +
|
---|
2532 | + XRCCTRL(*this, "ID_BROWSEGSSPLUGIN", wxButton)->Enable(enabled);
|
---|
2533 | +
|
---|
2534 | + if (!enabled) {
|
---|
2535 | + XRCCTRL(*this, "ID_GSSMODSTATUS", wxStaticText)->SetLabel(_("Disabled"));
|
---|
2536 | + } else {
|
---|
2537 | + if (pTextCtrl->IsModified()) {
|
---|
2538 | + pTextCtrl->SetModified(false);
|
---|
2539 | + LoadGssLibrary(pTextCtrl->GetValue());
|
---|
2540 | + }
|
---|
2541 | + if (IsGssLoaded()) {
|
---|
2542 | + XRCCTRL(*this, "ID_GSSMODSTATUS", wxStaticText)->SetLabel(_("Loaded successfully"));
|
---|
2543 | + } else {
|
---|
2544 | + XRCCTRL(*this, "ID_GSSMODSTATUS", wxStaticText)->SetLabel(GetGssLoadError());
|
---|
2545 | + }
|
---|
2546 | + }
|
---|
2547 | +
|
---|
2548 | + wxCheckBox *pDataEncCtrl = XRCCTRL(*this, "ID_ENABLEGSSDATAENCRYPT", wxCheckBox);
|
---|
2549 | + bool enabledDataEnc = pDataEncCtrl->GetValue();
|
---|
2550 | + pDataEncCtrl->Enable(enabled);
|
---|
2551 | +
|
---|
2552 | + XRCCTRL(*this, "ID_GSSPROTBUFSIZE", wxTextCtrl)->Enable(enabled && enabledDataEnc);
|
---|
2553 | +}
|
---|
2554 | diff --git a/src/interface/settings/optionspage_gssauth.h b/src/interface/settings/optionspage_gssauth.h
|
---|
2555 | new file mode 100644
|
---|
2556 | index 0000000..2e6b17a
|
---|
2557 | --- /dev/null
|
---|
2558 | +++ b/src/interface/settings/optionspage_gssauth.h
|
---|
2559 | @@ -0,0 +1,18 @@
|
---|
2560 | +#ifndef __OPTIONSPAGE_GSSAUTH_H__
|
---|
2561 | +#define __OPTIONSPAGE_GSSAUTH_H__
|
---|
2562 | +
|
---|
2563 | +class COptionsPageGssAuth : public COptionsPage
|
---|
2564 | +{
|
---|
2565 | +public:
|
---|
2566 | + virtual wxString GetResourceName() { return _T("ID_SETTINGS_CONNECTION_FTP_GSSAPI"); }
|
---|
2567 | + virtual bool LoadPage();
|
---|
2568 | + virtual bool SavePage();
|
---|
2569 | + virtual bool Validate();
|
---|
2570 | +
|
---|
2571 | +protected:
|
---|
2572 | + DECLARE_EVENT_TABLE()
|
---|
2573 | + void OnGssSettingChanged(wxCommandEvent& event);
|
---|
2574 | + void OnBrowse(wxCommandEvent& event);
|
---|
2575 | + void SetCtrlState();
|
---|
2576 | +};
|
---|
2577 | +#endif //__OPTIONSPAGE_GSSAUTH_H__
|
---|
2578 | diff --git a/src/interface/settings/settingsdialog.cpp b/src/interface/settings/settingsdialog.cpp
|
---|
2579 | index 69490b6..4d0611f 100644
|
---|
2580 | --- a/src/interface/settings/settingsdialog.cpp
|
---|
2581 | +++ b/src/interface/settings/settingsdialog.cpp
|
---|
2582 | @@ -7,6 +7,7 @@
|
---|
2583 | #include "optionspage_connection_active.h"
|
---|
2584 | #include "optionspage_connection_passive.h"
|
---|
2585 | #include "optionspage_ftpproxy.h"
|
---|
2586 | +#include "optionspage_gssauth.h"
|
---|
2587 | #include "optionspage_connection_sftp.h"
|
---|
2588 | #include "optionspage_filetype.h"
|
---|
2589 | #include "optionspage_fileexists.h"
|
---|
2590 | @@ -94,6 +95,7 @@ bool CSettingsDialog::LoadPages()
|
---|
2591 | AddPage(_("Active mode"), new COptionsPageConnectionActive, 2);
|
---|
2592 | AddPage(_("Passive mode"), new COptionsPageConnectionPassive, 2);
|
---|
2593 | AddPage(_("FTP Proxy"), new COptionsPageFtpProxy, 2);
|
---|
2594 | + AddPage(_("GSSAPI Auth"), new COptionsPageGssAuth, 2);
|
---|
2595 | AddPage(_("SFTP"), new COptionsPageConnectionSFTP, 1);
|
---|
2596 | AddPage(_("Generic proxy"), new COptionsPageProxy, 1);
|
---|
2597 | AddPage(_("Transfers"), new COptionsPageTransfer, 0);
|
---|