1 /*
2 **   RDP Password Checking Medusa Module
3 **
4 **   ------------------------------------------------------------------------
5 **    Copyright (C) 2015 Joe Mondloch
6 **    JoMo-Kun / jmk@foofus.net
7 **
8 **    This program is free software; you can redistribute it and/or modify
9 **    it under the terms of the GNU General Public License version 2,
10 **    as published by the Free Software Foundation
11 **
12 **    This program is distributed in the hope that it will be useful,
13 **    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 **    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 **    GNU General Public License for more details.
16 **
17 **    http://www.gnu.org/licenses/gpl.txt
18 **
19 **    This program is released under the GPL with the additional exemption
20 **    that compiling, linking, and/or using OpenSSL is allowed.
21 **
22 **   ------------------------------------------------------------------------
23 **
24 **   FreeRDP/client/Sample/freerdp.c
25  * FreeRDP: A Remote Desktop Protocol Implementation
26  * FreeRDP Test UI
27  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
28 **
29 */
30 
31 #include <sys/types.h>
32 #include <libgen.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include "module.h"
37 
38 #include <freerdp/freerdp.h>
39 #include <freerdp/gdi/gdi.h>
40 #include <freerdp/channels/channels.h>
41 
42 #ifndef HAVE_LIBFREERDP10
43 #include <freerdp/client/cmdline.h>
44 #endif
45 
46 #define MODULE_NAME    "rdp.mod"
47 #define MODULE_AUTHOR  "JoMo-Kun <jmk@foofus.net>"
48 #define MODULE_SUMMARY_USAGE  "Brute force module for RDP (Microsoft Terminal Server) sessions"
49 #define MODULE_VERSION    "0.1"
50 #define MODULE_VERSION_SVN "$Id: ssh.c 1403 2010-09-01 21:41:00Z jmk $"
51 #define MODULE_SUMMARY_FORMAT  "%s : version %s"
52 
53 #define PORT_RDP 3389
54 #define NTLM_HASH_BLANK "31D6CFE0D16AE931B73C59D7E0C089C0"
55 
56 typedef struct __MODULE_DATA {
57   char* szDomain;
58   int isPassTheHash;
59 } _MODULE_DATA;
60 
61 // Tells us whether we are to continue processing or not
62 enum MODULE_STATE
63 {
64   MSTATE_NEW,
65   MSTATE_RUNNING,
66   MSTATE_EXITING,
67   MSTATE_COMPLETE
68 };
69 
70 // Forward declarations
71 int tryLogin(_MODULE_DATA* _psSessionData, sLogin** login, freerdp* instance, char* szLogin, char* szPassword);
72 int initModule(sLogin* login, _MODULE_DATA *_psSessionData);
73 
74 void initWLog();
75 void tf_context_new(freerdp* instance, rdpContext* context);
76 void tf_context_free(freerdp* instance, rdpContext* context);
77 void tf_begin_paint(rdpContext* context);
78 void tf_end_paint(rdpContext* context);
79 int tf_receive_channel_data(freerdp* instance, int channelId, unsigned char* data, int size, int flags, int total_size);
80 int tf_pre_connect(freerdp* instance);
81 int tf_post_connect(freerdp* instance);
82 
83 extern FREERDP_API int freerdp_channels_global_init(void);
84 extern FREERDP_API int freerdp_channels_global_uninit(void);
85 
86 // Tell medusa how many parameters this module allows
getParamNumber()87 int getParamNumber()
88 {
89   return 0;
90 }
91 
92 // Displays information about the module and how it must be used
summaryUsage(char ** ppszSummary)93 void summaryUsage(char **ppszSummary)
94 {
95   // Memory for ppszSummary will be allocated here - caller is responsible for freeing it
96   int  iLength = 0;
97 
98   if (*ppszSummary == NULL)
99   {
100     iLength = strlen(MODULE_SUMMARY_USAGE) + strlen(MODULE_VERSION) + strlen(MODULE_SUMMARY_FORMAT) + 1;
101     *ppszSummary = (char*)malloc(iLength);
102     memset(*ppszSummary, 0, iLength);
103     snprintf(*ppszSummary, iLength, MODULE_SUMMARY_FORMAT, MODULE_SUMMARY_USAGE, MODULE_VERSION);
104   }
105   else
106   {
107     writeError(ERR_ERROR, "%s reports an error in summaryUsage() : ppszSummary must be NULL when called", MODULE_NAME);
108   }
109 }
110 
111 /* Display module usage information */
showUsage()112 void showUsage()
113 {
114   writeVerbose(VB_NONE, "%s (%s) %s :: %s\n", MODULE_NAME, MODULE_VERSION, MODULE_AUTHOR, MODULE_SUMMARY_USAGE);
115   writeVerbose(VB_NONE, "Available module options:");
116   writeVerbose(VB_NONE, "  DOMAIN:? [optional]");
117 #if defined(HAVE_LIBFREERDP12) || defined(HAVE_LIBFREERDP11PTH)
118   writeVerbose(VB_NONE, "  PASS:?  (PASSWORD*, HASH)");
119   writeVerbose(VB_NONE, "    PASSWORD: Use normal password.");
120   writeVerbose(VB_NONE, "    HASH:     Use a NTLM hash rather than a password.");
121 #endif
122   writeVerbose(VB_NONE, "");
123   writeVerbose(VB_NONE, "Usage example: \"-M rdp\"");
124 #if defined(HAVE_LIBFREERDP12) || defined(HAVE_LIBFREERDP11PTH)
125   writeVerbose(VB_NONE, "Usage example: \"-M rdp -m PASS:HASH -u Administrator -p 31D78236327B9619B14ED8EC9AB454C1");
126   writeVerbose(VB_NONE, "");
127   writeVerbose(VB_NONE, "Note: This module does NOT work against Microsoft Windows 2003/XP and earlier.");
128 #endif
129   writeVerbose(VB_NONE, "");
130   writeVerbose(VB_NONE, "*** There appears to be thread-safety issues within the FreeRDP library and/or this module. ***");
131   writeVerbose(VB_NONE, "*** It is recommended that you avoid using concurrent hosts/users (i.e., -T/-t).");
132   writeVerbose(VB_NONE, "");
133 }
134 
135 // The "main" of the medusa module world - this is what gets called to actually do the work
go(sLogin * logins,int argc,char * argv[])136 int go(sLogin* logins, int argc, char *argv[])
137 {
138   int i;
139   char *strtok_ptr, *pOpt, *pOptTmp;
140   _MODULE_DATA *psSessionData = NULL;
141 
142   psSessionData = malloc(sizeof(_MODULE_DATA));
143   memset(psSessionData, 0, sizeof(_MODULE_DATA));
144 
145   if ((argc < 0) || (argc > 2))
146   {
147     writeError(ERR_ERROR, "%s: Incorrect number of parameters passed to module (%d). Use \"-q\" option to display module usage.", MODULE_NAME, argc);
148     return FAILURE;
149   }
150   else
151   {
152     writeError(ERR_DEBUG_MODULE, "OMG teh %s module has been called!!", MODULE_NAME);
153 
154     for (i=0; i<argc; i++) {
155       pOptTmp = malloc( strlen(argv[i]) + 1);
156       memset(pOptTmp, 0, strlen(argv[i]) + 1);
157       strncpy(pOptTmp, argv[i], strlen(argv[i]));
158       writeError(ERR_DEBUG_MODULE, "Processing complete option: %s", pOptTmp);
159       pOpt = strtok_r(pOptTmp, ":", &strtok_ptr);
160       writeError(ERR_DEBUG_MODULE, "Processing option: %s", pOpt);
161 
162       if (strcmp(pOpt, "DOMAIN") == 0)
163       {
164         pOpt = strtok_r(NULL, "\0", &strtok_ptr);
165         writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
166 
167         if ( pOpt )
168         {
169           psSessionData->szDomain = malloc(strlen(pOpt) + 1);
170           memset(psSessionData->szDomain, 0, strlen(pOpt) + 1);
171           strncpy((char *) psSessionData->szDomain, pOpt, strlen(pOpt));
172         }
173         else
174           writeError(ERR_WARNING, "Method DOMAIN requires value to be set.");
175       }
176 #if defined(HAVE_LIBFREERDP12) || defined(HAVE_LIBFREERDP11PTH)
177       else if (strcmp(pOpt, "PASS") == 0) {
178         pOpt = strtok_r(NULL, "\0", &strtok_ptr);
179         writeError(ERR_DEBUG_MODULE, "Processing option parameter: %s", pOpt);
180 
181         if (pOpt == NULL)
182           writeError(ERR_WARNING, "Method PASS requires value to be set.");
183         else if (strcmp(pOpt, "PASSWORD") == 0)
184           psSessionData->isPassTheHash = FALSE;
185         else if (strcmp(pOpt, "HASH") == 0)
186           psSessionData->isPassTheHash = TRUE;
187         else
188           writeError(ERR_WARNING, "Invalid value for method PASS.");
189       }
190 #endif
191       else
192          writeError(ERR_WARNING, "Invalid method: %s.", pOpt);
193 
194       free(pOptTmp);
195     }
196 
197     initModule(logins, psSessionData);
198   }
199 
200   FREE(psSessionData);
201   return SUCCESS;
202 }
203 
initModule(sLogin * psLogin,_MODULE_DATA * _psSessionData)204 int initModule(sLogin* psLogin, _MODULE_DATA *_psSessionData)
205 {
206   enum MODULE_STATE nState = MSTATE_NEW;
207   sCredentialSet *psCredSet = NULL;
208 	freerdp* instance;
209 
210   /* Retrieve next available credential set to test */
211   psCredSet = malloc( sizeof(sCredentialSet) );
212   memset(psCredSet, 0, sizeof(sCredentialSet));
213 
214   if (getNextCredSet(psLogin, psCredSet) == FAILURE)
215   {
216     writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
217     nState = MSTATE_COMPLETE;
218   }
219   else if (psCredSet->psUser)
220   {
221     writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s user: %s", MODULE_NAME, psLogin->psServer->pHostIP, psCredSet->psUser->pUser);
222   }
223   else
224   {
225     writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s - no more available users to test.", MODULE_NAME, psLogin->psServer->pHostIP);
226     nState = MSTATE_COMPLETE;
227   }
228 
229   while (nState != MSTATE_COMPLETE)
230   {
231     switch (nState)
232     {
233       case MSTATE_NEW:
234 
235 #ifdef HAVE_LIBFREERDP12
236         initWLog();
237 #else
238         freerdp_channels_global_init();
239 #endif
240 
241 	      instance = freerdp_new();
242 	      instance->PreConnect = tf_pre_connect;
243 	      instance->PostConnect = tf_post_connect;
244 	      instance->ReceiveChannelData = tf_receive_channel_data;
245 
246 	      instance->ContextNew = (pContextNew)tf_context_new;
247 	      instance->ContextFree = tf_context_free;
248 	      freerdp_context_new(instance);
249 
250 #ifdef HAVE_LIBFREERDP10
251         instance->settings->ignore_certificate = TRUE;
252         instance->settings->authentication_only = TRUE;
253         instance->settings->hostname = psLogin->psServer->pHostIP;
254 #else
255         instance->settings->IgnoreCertificate = TRUE;
256         instance->settings->AuthenticationOnly = TRUE;
257         instance->settings->ServerHostname = psLogin->psServer->pHostIP;
258 #endif
259 
260         if (psLogin->psServer->psAudit->iPortOverride > 0)
261 #ifdef HAVE_LIBFREERDP10
262           instance->settings->port = psLogin->psServer->psAudit->iPortOverride;
263 #else
264           instance->settings->ServerPort = psLogin->psServer->psAudit->iPortOverride;
265 #endif
266         else
267 #ifdef HAVE_LIBFREERDP10
268           instance->settings->port = PORT_RDP;
269 #else
270           instance->settings->ServerPort = PORT_RDP;
271 #endif
272 
273         writeError(ERR_DEBUG_MODULE, "Id: %d initialized FreeRDP instance.", psLogin->iId);
274         nState = MSTATE_RUNNING;
275         break;
276       case MSTATE_RUNNING:
277         nState = tryLogin(_psSessionData, &psLogin, instance, psCredSet->psUser->pUser, psCredSet->pPass);
278 
279         if (getNextCredSet(psLogin, psCredSet) == FAILURE)
280         {
281           writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
282           nState = MSTATE_EXITING;
283         }
284         else
285         {
286           if (psCredSet->iStatus == CREDENTIAL_DONE)
287           {
288             writeError(ERR_DEBUG_MODULE, "[%s] No more available credential sets to test.", MODULE_NAME);
289             nState = MSTATE_EXITING;
290           }
291           else if (psCredSet->iStatus == CREDENTIAL_NEW_USER)
292           {
293             writeError(ERR_DEBUG_MODULE, "[%s] Starting testing for new user: %s.", MODULE_NAME, psCredSet->psUser->pUser);
294             nState = MSTATE_NEW;
295           }
296           else
297             writeError(ERR_DEBUG_MODULE, "[%s] Next credential set - user: %s password: %s", MODULE_NAME, psCredSet->psUser->pUser, psCredSet->pPass);
298         }
299 
300         break;
301       case MSTATE_EXITING:
302 #ifdef HAVE_LIBFREERDP12
303         freerdp_free(instance);
304 #else
305         freerdp_channels_global_uninit();
306 #endif
307         nState = MSTATE_COMPLETE;
308         break;
309       default:
310         writeError(ERR_CRITICAL, "Unknown %s module state %d", MODULE_NAME, nState);
311 
312 #ifdef HAVE_LIBFREERDP12
313         freerdp_free(instance);
314 #else
315         freerdp_channels_global_uninit();
316 #endif
317         psLogin->iResult = LOGIN_RESULT_UNKNOWN;
318 
319         return FAILURE;
320     }
321   }
322 
323   FREE(psCredSet);
324   return SUCCESS;
325 }
326 
327 /* Module Specific Functions */
328 #ifdef HAVE_LIBFREERDP12
CallbackAppenderMessage(const wLogMessage * msg)329 void CallbackAppenderMessage(const wLogMessage *msg)
330 {
331   writeError(ERR_DEBUG_MODULE, "[%s] FreeRDP: %s", MODULE_NAME, msg->TextString);
332 }
333 
CallbackAppenderData(const wLogMessage * msg)334 void CallbackAppenderData(const wLogMessage *msg)
335 {
336   writeError(ERR_DEBUG_MODULE, "[%s] FreeRDP CallbackAppenderData()", MODULE_NAME);
337 }
338 
CallbackAppenderImage(const wLogMessage * msg)339 void CallbackAppenderImage(const wLogMessage *msg)
340 {
341   writeError(ERR_DEBUG_MODULE, "[%s] FreeRDP CallbackAppenderImage()", MODULE_NAME);
342 }
343 
CallbackAppenderPackage(const wLogMessage * msg)344 void CallbackAppenderPackage(const wLogMessage *msg)
345 {
346   writeError(ERR_DEBUG_MODULE, "[%s] FreeRDP CallbackAppenderPackage()", MODULE_NAME);
347 }
348 
initWLog()349 void initWLog()
350 {
351   wLog* root;
352   wLogLayout* layout;
353   wLogAppender* appender;
354 
355   WLog_Init();
356 
357   writeError(ERR_DEBUG_MODULE, "[%s] Initializing FreeRDP WLog", MODULE_NAME);
358 
359   root = WLog_GetRoot();
360 
361   WLog_SetLogAppenderType(root, WLOG_APPENDER_CALLBACK);
362 
363   appender = WLog_GetLogAppender(root);
364 
365   WLog_CallbackAppender_SetCallbacks(root, (wLogCallbackAppender*) appender,
366     CallbackAppenderMessage, CallbackAppenderImage, CallbackAppenderPackage,
367     CallbackAppenderData);
368 
369   layout = WLog_GetLogLayout(root);
370   WLog_Layout_SetPrefixFormat(root, layout, "%mn");
371 
372   WLog_OpenAppender(root);
373 }
374 #endif
375 
376 struct tf_info
377 {
378 	void* data;
379 };
380 typedef struct tf_info tfInfo;
381 
382 struct tf_context
383 {
384 	rdpContext _p;
385 
386 	tfInfo* tfi;
387 };
388 typedef struct tf_context tfContext;
389 
tf_context_new(freerdp * instance,rdpContext * context)390 void tf_context_new(freerdp* instance, rdpContext* context)
391 {
392 	context->channels = freerdp_channels_new();
393 }
394 
tf_context_free(freerdp * instance,rdpContext * context)395 void tf_context_free(freerdp* instance, rdpContext* context)
396 {
397 
398 }
399 
tf_begin_paint(rdpContext * context)400 void tf_begin_paint(rdpContext* context)
401 {
402 	rdpGdi* gdi = context->gdi;
403 	gdi->primary->hdc->hwnd->invalid->null = 1;
404 }
405 
tf_end_paint(rdpContext * context)406 void tf_end_paint(rdpContext* context)
407 {
408 	rdpGdi* gdi = context->gdi;
409 
410 	if (gdi->primary->hdc->hwnd->invalid->null)
411 		return;
412 }
413 
tf_receive_channel_data(freerdp * instance,int channelId,unsigned char * data,int size,int flags,int total_size)414 int tf_receive_channel_data(freerdp* instance, int channelId, unsigned char* data, int size, int flags, int total_size)
415 {
416 	return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
417 }
418 
tf_pre_connect(freerdp * instance)419 int tf_pre_connect(freerdp* instance)
420 {
421 	tfInfo* tfi;
422 	tfContext* context;
423 	rdpSettings* settings;
424 
425 	context = (tfContext*) instance->context;
426 
427 	tfi = (tfInfo*) malloc(sizeof(tfInfo));
428 	memset(tfi, 0, sizeof(tfInfo));
429 
430 	context->tfi = tfi;
431 
432 	settings = instance->settings;
433 
434 #ifdef HAVE_LIBFREERDP10
435   settings->order_support[NEG_DSTBLT_INDEX] = TRUE;
436   settings->order_support[NEG_PATBLT_INDEX] = TRUE;
437   settings->order_support[NEG_SCRBLT_INDEX] = TRUE;
438   settings->order_support[NEG_OPAQUE_RECT_INDEX] = TRUE;
439   settings->order_support[NEG_DRAWNINEGRID_INDEX] = TRUE;
440   settings->order_support[NEG_MULTIDSTBLT_INDEX] = TRUE;
441   settings->order_support[NEG_MULTIPATBLT_INDEX] = TRUE;
442   settings->order_support[NEG_MULTISCRBLT_INDEX] = TRUE;
443   settings->order_support[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
444   settings->order_support[NEG_MULTI_DRAWNINEGRID_INDEX] = TRUE;
445   settings->order_support[NEG_LINETO_INDEX] = TRUE;
446   settings->order_support[NEG_POLYLINE_INDEX] = TRUE;
447   settings->order_support[NEG_MEMBLT_INDEX] = TRUE;
448   settings->order_support[NEG_MEM3BLT_INDEX] = TRUE;
449   settings->order_support[NEG_SAVEBITMAP_INDEX] = TRUE;
450   settings->order_support[NEG_GLYPH_INDEX_INDEX] = TRUE;
451   settings->order_support[NEG_FAST_INDEX_INDEX] = TRUE;
452   settings->order_support[NEG_FAST_GLYPH_INDEX] = TRUE;
453   settings->order_support[NEG_POLYGON_SC_INDEX] = TRUE;
454   settings->order_support[NEG_POLYGON_CB_INDEX] = TRUE;
455   settings->order_support[NEG_ELLIPSE_SC_INDEX] = TRUE;
456   settings->order_support[NEG_ELLIPSE_CB_INDEX] = TRUE;
457 #else
458 	settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
459 	settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
460 	settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
461 	settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
462 	settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = TRUE;
463 	settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = TRUE;
464 	settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = TRUE;
465 	settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = TRUE;
466 	settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
467 	settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = TRUE;
468 	settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
469 	settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
470 	settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE;
471 	settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE;
472 	settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = TRUE;
473 	settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
474 	settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
475 	settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
476 	settings->OrderSupport[NEG_POLYGON_SC_INDEX] = TRUE;
477 	settings->OrderSupport[NEG_POLYGON_CB_INDEX] = TRUE;
478 	settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = TRUE;
479 	settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = TRUE;
480 #endif
481 
482 	freerdp_channels_pre_connect(instance->context->channels, instance);
483 
484 	return TRUE;
485 }
486 
tf_post_connect(freerdp * instance)487 int tf_post_connect(freerdp* instance)
488 {
489 	gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP | CLRBUF_32BPP, NULL);
490 
491 	instance->update->BeginPaint = tf_begin_paint;
492 	instance->update->EndPaint = tf_end_paint;
493 
494 	freerdp_channels_post_connect(instance->context->channels, instance);
495 
496 	return TRUE;
497 }
498 
tryLogin(_MODULE_DATA * _psSessionData,sLogin ** psLogin,freerdp * instance,char * szLogin,char * szPassword)499 int tryLogin(_MODULE_DATA* _psSessionData, sLogin** psLogin, freerdp* instance, char* szLogin, char* szPassword)
500 {
501   int nRet;
502   int old_stderr;
503 
504 #ifdef HAVE_LIBFREERDP10
505   instance->settings->username = szLogin;
506 #else
507   instance->settings->Username = szLogin;
508 #endif
509 
510   /* If the domain is not defined, local accounts are targeted */
511   if (_psSessionData->szDomain)
512 #ifdef HAVE_LIBFREERDP10
513     instance->settings->domain = _psSessionData->szDomain;
514 #else
515     instance->settings->Domain = _psSessionData->szDomain;
516 #endif
517 
518   /* Pass-the-hash support added to FreeRDP 1.2.x development tree */
519 #if defined(HAVE_LIBFREERDP12) || defined(HAVE_LIBFREERDP11PTH)
520   if (_psSessionData->isPassTheHash)
521   {
522     instance->settings->ConsoleSession = TRUE;
523     instance->settings->RestrictedAdminModeRequired = TRUE;
524     instance->settings->PasswordHash = szPassword;
525   }
526   else
527     instance->settings->Password = szPassword;
528 #elif HAVE_LIBFREERDP11
529     instance->settings->Password = szPassword;
530 #else
531     instance->settings->password = szPassword;
532 #endif
533 
534   /* Blank password support
535 
536      FreeRDP does not support blank passwords. It attempts to pull credentials from a local
537      SAM file if a password of length 0 is supplied. We're using pass-the-hash to get
538      around this issue.
539   */
540   if (strlen(szPassword) == 0)
541   {
542 #if defined(HAVE_LIBFREERDP12) || defined(HAVE_LIBFREERDP11PTH)
543     writeError(ERR_DEBUG_MODULE, "[%s] Using pass-the-hash to test blank password.", MODULE_NAME);
544     instance->settings->ConsoleSession = TRUE;
545     instance->settings->RestrictedAdminModeRequired = TRUE;
546     instance->settings->PasswordHash = NTLM_HASH_BLANK;
547 #else
548     writeError(ERR_WARNING, "[%s] FreeRDP (version < 1.2) does not support blank passwords.", MODULE_NAME);
549     (*psLogin)->iResult = LOGIN_RESULT_UNKNOWN;
550     nRet = MSTATE_RUNNING;
551     setPassResult((*psLogin), szPassword);
552     return(nRet);
553 #endif
554   }
555 
556 #ifndef HAVE_LIBFREERDP10
557 	freerdp_client_load_addins(instance->context->channels, instance->settings);
558 #endif
559 
560 #ifndef HAVE_LIBFREERDP12
561   /* Suppress library FreeRDP pre-version 1.2 output */
562   if ((iVerboseLevel <= 5) && (iErrorLevel <= 5))
563   {
564     pthread_mutex_lock(&(*psLogin)->psServer->psAudit->ptmMutex);
565     old_stderr = dup(1);
566     (void)(freopen("/dev/null", "w", stderr) + 1); /* ignore return code */
567 
568     nRet = freerdp_connect(instance);
569 
570     fclose(stderr);
571     stderr = fdopen(old_stderr, "w");
572     pthread_mutex_unlock(&(*psLogin)->psServer->psAudit->ptmMutex);
573   }
574   else
575 #endif
576     nRet = freerdp_connect(instance);
577 
578   writeError(ERR_DEBUG_MODULE, "[%s] freerdp_connect exit code: %d", MODULE_NAME, nRet);
579 	if (nRet == 1)
580   {
581     writeError(ERR_DEBUG_MODULE, "[%s] Login attempt successful.", MODULE_NAME);
582     (*psLogin)->iResult = LOGIN_RESULT_SUCCESS;
583     nRet = MSTATE_EXITING;
584   }
585   else
586   {
587     writeError(ERR_DEBUG_MODULE, "[%s] Login attempt failed.", MODULE_NAME);
588     (*psLogin)->iResult = LOGIN_RESULT_FAIL;
589     nRet = MSTATE_NEW;
590   }
591 
592   setPassResult((*psLogin), szPassword);
593   return(nRet);
594 }
595