4141#include <sys/types.h>
4242
4343#include <pwd.h>
44- #ifdef WINDOWS
45- #include <logonuser.h>
46- #endif
4744#include <stdio.h>
4845#include <string.h>
4946#include <stdarg.h>
5956#include "auth-options.h"
6057#include "authfd.h"
6158
59+ #ifdef WINDOWS
60+ #include "logonuser.h"
61+ #include "monitor_wrap.h"
62+ #endif
63+
6264extern Buffer loginmsg ;
6365extern ServerOptions options ;
6466
@@ -228,10 +230,53 @@ sys_auth_passwd(Authctxt *authctxt, const char *password)
228230}
229231
230232#elif defined(WINDOWS )
233+ HANDLE password_auth_token = NULL ;
234+ HANDLE process_custom_lsa_auth (char * , const char * , char * );
235+
236+ void
237+ sys_auth_passwd_lsa (Authctxt * authctxt , const char * password )
238+ {
239+ char * lsa_auth_pkg = NULL ;
240+ wchar_t * lsa_auth_pkg_w = NULL ;
241+ int domain_len = 0 , lsa_auth_pkg_len = 0 ;
242+ HKEY reg_key = 0 ;
243+ REGSAM mask = STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_WOW64_64KEY ;
244+
245+ if ((RegOpenKeyExW (HKEY_LOCAL_MACHINE , L"SOFTWARE\\OpenSSH" , 0 , mask , & reg_key ) == ERROR_SUCCESS ) &&
246+ (RegQueryValueExW (reg_key , L"LSAAuthenticationPackage" , 0 , NULL , NULL , & lsa_auth_pkg_len ) == ERROR_SUCCESS )) {
247+ lsa_auth_pkg_w = (wchar_t * ) malloc (lsa_auth_pkg_len ); // lsa_auth_pkg_len includes the null terminating character.
248+ if (!lsa_auth_pkg_w )
249+ fatal ("%s: out of memory" , __func__ );
250+
251+ memset (lsa_auth_pkg_w , 0 , lsa_auth_pkg_len );
252+ if (RegQueryValueExW (reg_key , L"LSAAuthenticationPackage" , 0 , NULL , (LPBYTE )lsa_auth_pkg_w , & lsa_auth_pkg_len ) == ERROR_SUCCESS ) {
253+ lsa_auth_pkg = utf16_to_utf8 (lsa_auth_pkg_w );
254+ if (!lsa_auth_pkg )
255+ fatal ("utf16_to_utf8 failed to convert lsa_auth_pkg_w:%ls" , lsa_auth_pkg_w );
256+
257+ debug ("Authenticating using LSA Auth Package:%ls" , lsa_auth_pkg_w );
258+ password_auth_token = process_custom_lsa_auth (authctxt -> pw -> pw_name , password , lsa_auth_pkg );
259+ }
260+ }
261+
262+ done :
263+ if (lsa_auth_pkg_w )
264+ free (lsa_auth_pkg_w );
265+
266+ if (lsa_auth_pkg )
267+ free (lsa_auth_pkg );
268+
269+ if (reg_key )
270+ RegCloseKey (reg_key );
271+ }
272+
231273/*
232- * Authenticate on Windows - Call LogonUser and retrieve user token
274+ * Authenticate on Windows
275+ * - Call LogonUser and retrieve user token
276+ * - If LogonUser fails, then try the LSA (Local Security Authority) authentication.
233277*/
234- int sys_auth_passwd (Authctxt * authctxt , const char * password )
278+ int
279+ sys_auth_passwd (Authctxt * authctxt , const char * password )
235280{
236281 wchar_t * user_utf16 = NULL , * udom_utf16 = NULL , * pwd_utf16 = NULL , * tmp ;
237282 HANDLE token = NULL ;
@@ -249,25 +294,33 @@ int sys_auth_passwd(Authctxt *authctxt, const char *password)
249294 }
250295
251296 if (LogonUserExExWHelper (user_utf16 , udom_utf16 , pwd_utf16 , LOGON32_LOGON_NETWORK_CLEARTEXT ,
252- LOGON32_PROVIDER_DEFAULT , NULL , & token , NULL , NULL , NULL , NULL ) == FALSE) {
253- if (GetLastError () == ERROR_PASSWORD_MUST_CHANGE )
254- /*
255- * TODO - need to add support to force password change
256- * by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
257- */
297+ LOGON32_PROVIDER_DEFAULT , NULL , & token , NULL , NULL , NULL , NULL ) == TRUE)
298+ password_auth_token = token ;
299+ else {
300+ if (GetLastError () == ERROR_PASSWORD_MUST_CHANGE )
301+ /*
302+ * TODO - need to add support to force password change
303+ * by sending back SSH_MSG_USERAUTH_PASSWD_CHANGEREQ
304+ */
258305 error ("password for user %s has expired" , authctxt -> pw -> pw_name );
259- else
260- debug ("failed to logon user: %ls domain: %ls error:%d" , user_utf16 , udom_utf16 , GetLastError ());
261- goto done ;
262- }
306+ else {
307+ debug ("Windows authentication failed for user: %ls domain: %ls error:%d" , user_utf16 , udom_utf16 , GetLastError ());
263308
264- authctxt -> auth_token = (void * )(INT_PTR )token ;
265- r = 1 ;
309+ /* If LSA authentication package is configured then it will return the auth_token */
310+ sys_auth_passwd_lsa (authctxt , password );
311+ }
312+ }
313+
266314done :
315+ if (password_auth_token )
316+ r = 1 ;
317+
267318 if (user_utf16 )
268319 free (user_utf16 );
320+
269321 if (pwd_utf16 )
270322 SecureZeroMemory (pwd_utf16 , sizeof (wchar_t ) * wcslen (pwd_utf16 ));
323+
271324 return r ;
272325}
273326#endif /* WINDOWS */
0 commit comments