@@ -493,7 +493,7 @@ do_authenticated1(Authctxt *authctxt)
493493int do_exec_windows (Session * s , const char * command , int pty ) {
494494 int pipein [2 ], pipeout [2 ], pipeerr [2 ], r ;
495495 char * exec_command = NULL , * progdir = w32_programdir ();
496- wchar_t * exec_command_w = NULL ;
496+ wchar_t * exec_command_w = NULL , * pw_dir_w ;
497497
498498 if (s -> is_subsystem >= SUBSYSTEM_INT_SFTP_ERROR )
499499 {
@@ -503,10 +503,12 @@ int do_exec_windows(Session *s, const char *command, int pty) {
503503 }
504504
505505 /* Create three pipes for stdin, stdout and stderr */
506- if (pipe (pipein ) == -1 || pipe (pipeout ) == -1 || pipe (pipeerr ) == -1 ) {
507- error ("%s: cannot create pipe: %.100s" , __func__ , strerror (errno ));
508- return -1 ;
509- }
506+ if (pipe (pipein ) == -1 || pipe (pipeout ) == -1 || pipe (pipeerr ) == -1 )
507+ fatal ("%s: cannot create pipe: %.100s" , __func__ , strerror (errno ));
508+
509+ if ((pw_dir_w = utf8_to_utf16 (s -> pw -> pw_dir )) == NULL )
510+ fatal ("%s: out of memory" );
511+
510512
511513 set_nonblock (pipein [0 ]);
512514 set_nonblock (pipein [1 ]);
@@ -536,45 +538,85 @@ int do_exec_windows(Session *s, const char *command, int pty) {
536538 memcpy (exec_command + strlen (progdir ) + 1 , command , strlen (command ) + 1 );
537539 }
538540 } else {
539- char * shell_host = pty ? "ssh-shellhost.exe -t " : "ssh-shellhost.exe " ;
540- exec_command = malloc (strlen (progdir ) + strlen (shell_host ) + (command ? strlen (command ) : 0 ));
541+ char * shell_host = pty ? "ssh-shellhost.exe " : "ssh-shellhost.exe -nopty " , * c ;
542+ exec_command = malloc (strlen (progdir ) + 1 + strlen (shell_host ) + (command ? strlen (command ) : 0 ) + 1 );
541543 if (exec_command == NULL )
542544 fatal ("%s, out of memory" );
543-
545+ c = exec_command ;
546+ memcpy (c , progdir , strlen (progdir ));
547+ c += strlen (progdir );
548+ * c ++ = '\\' ;
549+ memcpy (c , shell_host , strlen (shell_host ));
550+ c += strlen (shell_host );
551+ if (command ) {
552+ memcpy (c , command , strlen (command ));
553+ c += strlen (command );
554+ }
555+ * c == '\0' ;
544556 }
545-
546- wchar_t * pw_dir_utf16 = utf8_to_utf16 (s -> pw -> pw_dir );
547- extern int debug_flag ;
548557
549- PROCESS_INFORMATION pi ;
550- STARTUPINFOW si ;
558+ /* setup Environment varibles */
559+ {
560+ wchar_t * tmp ;
561+ char buf [128 ];
562+ char * laddr ;
551563
552- BOOL b ;
564+ if ((tmp == utf8_to_utf16 (s -> pw -> pw_name )) != NULL )
565+ fatal ("%s, out of memory" );
566+ SetEnvironmentVariableW (L"USERNAME" , tmp );
567+ free (tmp );
553568
554- HANDLE hToken = INVALID_HANDLE_VALUE ;
569+ if (s -> display )
570+ SetEnvironmentVariableW (L"DISPLAY" , s -> display );
571+
555572
573+ //_wchdir(pw_dir_w);
556574
557- char cmd [1024 ];
558- char * exec_command ;
559- char * laddr ;
560- char buf [256 ];
575+ SetEnvironmentVariableW (L"HOMEPATH" , pw_dir_w );
576+ SetEnvironmentVariableW (L"USERPROFILE" , pw_dir_w );
561577
578+ if (pw_dir_w [1 ] == L':' ) {
579+ wchar_t wc = pw_dir_w [2 ];
580+ pw_dir_w [2 ] = L'\0' ;
581+ SetEnvironmentVariableW (L"HOMEDRIVE" , pw_dir_w );
582+ }
562583
584+ snprintf (buf , sizeof buf , "%.50s %d %d" ,
585+ get_remote_ipaddr (), get_remote_port (), get_local_port ());
563586
564- if (!command )
565- {
566- exec_command = s -> pw -> pw_shell ;
567- }
568- else
569- {
570- exec_command = command ;
571- }
587+ SetEnvironmentVariableA ("SSH_CLIENT" , buf );
572588
589+ laddr = get_local_ipaddr (packet_get_connection_in ());
573590
574- int retcode = -1 ;
575- if ((!s -> is_subsystem ) && (s -> ttyfd != -1 ))
576- {
591+ snprintf (buf , sizeof buf , "%.50s %d %.50s %d" ,
592+ get_remote_ipaddr (), get_remote_port (), laddr , get_local_port ());
593+
594+ free (laddr );
595+
596+ SetEnvironmentVariableA ("SSH_CONNECTION" , buf );
597+
598+ if (original_command )
599+ SetEnvironmentVariableA ("SSH_ORIGINAL_COMMAND" , original_command );
600+
601+
602+ if ((s -> term ) && (s -> term [0 ]))
603+ SetEnvironmentVariable ("TERM" , s -> term );
604+
605+ if (!s -> is_subsystem ) {
606+ snprintf (buf , sizeof buf , "%s@%s $P$G" , s -> pw -> pw_name , getenv ("COMPUTERNAME" ));
607+ SetEnvironmentVariableA ("PROMPT" , buf );
608+ }
577609 }
610+
611+ extern int debug_flag ;
612+
613+ PROCESS_INFORMATION pi ;
614+ STARTUPINFOW si ;
615+
616+ BOOL b ;
617+
618+ HANDLE hToken = INVALID_HANDLE_VALUE ;
619+
578620
579621 /*
580622 * Assign sockets to StartupInfo
@@ -602,122 +644,21 @@ int do_exec_windows(Session *s, const char *command, int pty) {
602644 si .hStdError = (HANDLE )sfd_to_handle (pipeerr [1 ]);
603645 si .lpDesktop = NULL ;
604646
605- SetEnvironmentVariable ("USER" , s -> pw -> pw_name );
606- SetEnvironmentVariable ("USERNAME" , s -> pw -> pw_name );
607- SetEnvironmentVariable ("LOGNAME" , s -> pw -> pw_name );
608-
609- /*
610- * If we get this far, the user has already been authenticated
611- * We should either have a user token in authctxt -> methoddata
612- * (e.g. for password auth) or we need to create a more restrictive
613- * token using CreateUserToken for non-password auth mechanisms.
614- */
615-
616647 hToken = s -> authctxt -> methoddata ;
617648
618-
619- if (s -> display )
620- {
621- SetEnvironmentVariable ("DISPLAY" , s -> display );
622- }
623-
624- /*
625- * Change to users home directory
626- * TODO - pw_dir is utf-8, convert it to utf-16 and call _wchdir
627- * also change subsequent calls to SetEnvironmentVariable
628- */
629-
630- _wchdir (pw_dir_utf16 );
631-
632- SetEnvironmentVariableW (L"HOME" , pw_dir_utf16 );
633- SetEnvironmentVariableW (L"USERPROFILE" , pw_dir_utf16 );
634-
635- wchar_t * wstr , wchr ;
636- wstr = wcschr (pw_dir_utf16 , L':' );
637- if (wstr ) {
638- wchr = * (wstr + 1 );
639- * (wstr + 1 ) = '\0' ;
640- SetEnvironmentVariableW (L"HOMEDRIVE" , pw_dir_utf16 );
641- * (wstr + 1 ) = wchr ;
642- SetEnvironmentVariableW (L"HOMEPATH" , (wstr + 1 ));
643- }
644-
645- // find the server name of the domain controller which created this token
646- GetDomainFromToken (& hToken , buf , sizeof (buf ));
647- if (buf [0 ])
648- SetEnvironmentVariable ("USERDOMAIN" , buf );
649-
650- /*
651- * Set SSH_CLIENT variable.
652- */
653-
654- snprintf (buf , sizeof buf , "%.50s %d %d" ,
655- get_remote_ipaddr (), get_remote_port (), get_local_port ());
656-
657- SetEnvironmentVariableA ("SSH_CLIENT" , buf );
658-
659- /*
660- * Set SSH_CONNECTION variable.
661- */
662-
663- laddr = get_local_ipaddr (packet_get_connection_in ());
664-
665- snprintf (buf , sizeof buf , "%.50s %d %.50s %d" ,
666- get_remote_ipaddr (), get_remote_port (), laddr , get_local_port ());
667-
668- free (laddr );
669-
670- SetEnvironmentVariableA ("SSH_CONNECTION" , buf );
671-
672- if (original_command )
673- SetEnvironmentVariableA ("SSH_ORIGINAL_COMMAND" , original_command );
674-
675-
676- // set better prompt for Windows cmd shell
677- if (!s -> is_subsystem ) {
678- snprintf (buf , sizeof buf , "%s@%s $P$G" , s -> pw -> pw_name , getenv ("COMPUTERNAME" ));
679- SetEnvironmentVariableA ("PROMPT" , buf );
680- }
681-
682- /*
683- * Get the current user's name (associated with sshd thread).
684- */
685-
686- debug3 ("Home path before CreateProcessAsUser [%ls]" , s -> pw -> pw_dir );
687-
688- DWORD size = 256 ;
689-
690- char name [256 ];
691-
692- GetUserName (name , & size );
693-
694- if ((s -> term ) && (s -> term [0 ]))
695- SetEnvironmentVariable ("TERM" , s -> term );
696- /*
697- * Create new process as other user using access token object.
698- */
699-
700649 debug ("Executing command: %s" , exec_command );
701650
702- /*
703- * Create the child process
704- */
651+ /* Create the child process */
705652
706- wchar_t exec_command_w [ MAX_PATH ] ;
653+ exec_command_w = utf8_to_utf16 ( exec_command ) ;
707654
708- MultiByteToWideChar (CP_UTF8 , 0 , exec_command , -1 , exec_command_w , MAX_PATH );
709- DWORD dwStartupFlags = DETACHED_PROCESS ;// CREATE_SUSPENDED; // 0
710-
711- SetConsoleCtrlHandler (NULL , FALSE);
712-
713- wchar_t * p_dir = utf8_to_utf16 (s -> pw -> pw_dir );
714655 if (debug_flag )
715656 b = CreateProcessW (NULL , exec_command_w , NULL , NULL , TRUE,
716- /*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags , NULL , pw_dir_utf16 ,
657+ DETACHED_PROCESS , NULL , pw_dir_w ,
717658 & si , & pi );
718659 else
719660 b = CreateProcessAsUserW (hToken , NULL , exec_command_w , NULL , NULL , TRUE,
720- /*CREATE_NEW_PROCESS_GROUP*/ dwStartupFlags , NULL , pw_dir_utf16 ,
661+ DETACHED_PROCESS , NULL , pw_dir_w ,
721662 & si , & pi );
722663
723664 if (!b )
@@ -728,7 +669,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
728669
729670 exit (1 );
730671 }
731- else if (s -> ttyfd != -1 ) { /*attach to shell console */
672+ else if (pty ) { /*attach to shell console */
732673 FreeConsole ();
733674 if (!debug_flag )
734675 ImpersonateLoggedOnUser (hToken );
@@ -748,23 +689,9 @@ int do_exec_windows(Session *s, const char *command, int pty) {
748689 }
749690 }
750691
751- /*
752- * Save token used for create child process. We'll need it on cleanup
753- * to clean up DACL of Winsta0.
754- */
755-
756- /*
757- * Log the process handle (fake it as the pid) for termination lookups
758- */
759-
760692 s -> pid = pi .dwProcessId ;
761693 sw_add_child (pi .hProcess , pi .dwProcessId );
762694
763- // Add the child process created to select mux so that during our select data call we know if the process has exited
764- /* TODO - fix thi s*/
765- //int WSHELPAddChildToWatch ( HANDLE processtowatch);
766- //WSHELPAddChildToWatch ( pi.hProcess);
767-
768695 /*
769696 * Set interactive/non-interactive mode.
770697 */
@@ -780,9 +707,7 @@ int do_exec_windows(Session *s, const char *command, int pty) {
780707 close (pipeout [1 ]);
781708 close (pipeerr [1 ]);
782709
783- ResumeThread (pi .hThread ); /* now let cmd shell main thread be active s we have closed all i/o file handle that cmd will use */
784- SetConsoleCtrlHandler (NULL , TRUE);
785-
710+
786711 /*
787712 * Close child thread handles as we do not need it. Process handle we keep so that we can know if it has died o not
788713 */
0 commit comments