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