2929* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030*/
3131
32+ #define WIN32_NO_STATUS
3233#include <Windows.h>
34+ #undef WIN32_NO_STATUS
3335#include <Ntsecapi.h>
34- // #include <ntstatus.h>
36+ #include <ntstatus.h>
3537#include "agent.h"
3638#include "agent-request.h"
3739
40+ static void
41+ InitLsaString (LSA_STRING * lsa_string , const char * str )
42+ {
43+ if (str == NULL )
44+ memset (lsa_string , 0 , sizeof (LSA_STRING ));
45+ else {
46+ lsa_string -> Buffer = str ;
47+ lsa_string -> Length = strlen (str );
48+ lsa_string -> MaximumLength = lsa_string -> Length + 1 ;
49+ }
50+ }
3851
39- int process_authagent_request (struct sshbuf * request , struct sshbuf * response , struct agent_connection * con ) {
40- while (1 )
41- {
42- HANDLE lsa_handle ;
43- PLSA_OPERATIONAL_MODE mode ;
44- ULONG auth_package_id ;
45- NTSTATUS ret ;
46- KERB_S4U_LOGON * s4u_logon ;
47- size_t logon_info_size ;
48- LSA_STRING logon_process_name , auth_package_name , originName ;
49- InitLsaString (& logon_process_name , "ssh-agent" );
50- //InitLsaString(&auth_package_name, MICROSOFT_KERBEROS_NAME_A);
51- InitLsaString (& auth_package_name , "Negotiate" );
52- InitLsaString (& originName , "sshd" );
53- if (ret = LsaRegisterLogonProcess (& logon_process_name , & lsa_handle , & mode ) != STATUS_SUCCESS )
54- break ;
55-
56- if (ret = LsaLookupAuthenticationPackage (lsa_handle , & auth_package_name , & auth_package_id ) != STATUS_SUCCESS )
57- break ;
58- #define USER_NAME L"user@domain"
59- logon_info_size = sizeof (KERB_S4U_LOGON );
60- logon_info_size += (wcslen (USER_NAME ) * 2 + 2 );
61- s4u_logon = malloc (logon_info_size );
62- s4u_logon -> MessageType = KerbS4ULogon ;
63- s4u_logon -> Flags = 0 ;
64- s4u_logon -> ClientUpn .Length = wcslen (USER_NAME ) * 2 ;
65- s4u_logon -> ClientUpn .MaximumLength = s4u_logon -> ClientUpn .Length ;
66- s4u_logon -> ClientUpn .Buffer = (WCHAR * )(s4u_logon + 1 );
67- memcpy (s4u_logon -> ClientUpn .Buffer , USER_NAME , s4u_logon -> ClientUpn .Length + 2 );
68- s4u_logon -> ClientRealm .Length = 0 ;
69- s4u_logon -> ClientRealm .MaximumLength = 0 ;
70- s4u_logon -> ClientRealm .Buffer = 0 ;
71-
72- TOKEN_SOURCE sourceContext ;
73- RtlCopyMemory (
74- sourceContext .SourceName ,
75- ".Jobs " ,
76- sizeof (sourceContext .SourceName )
77- );
78-
79- if (AllocateLocallyUniqueId (& sourceContext .SourceIdentifier ) != TRUE)
80- break ;
81-
82- PKERB_INTERACTIVE_PROFILE pProfile = NULL ;
83- LUID logonId ;
84- QUOTA_LIMITS quotas ;
85- NTSTATUS subStatus ;
86- DWORD cbProfile ;
87- HANDLE hToken = INVALID_HANDLE_VALUE ;
88- if (ret = LsaLogonUser (lsa_handle , & originName , Network , auth_package_id , s4u_logon , logon_info_size , NULL , & sourceContext ,
89- (PVOID * )& pProfile ,
90- & cbProfile ,
91- & logonId ,
92- & hToken ,
93- & quotas ,
94- & subStatus ) != STATUS_SUCCESS )
95- break ;
96-
97- CloseHandle (hToken );
52+ static HANDLE
53+ generate_user_token (wchar_t * user ) {
54+ HANDLE lsa_handle = 0 , token = 0 ;;
55+ LSA_OPERATIONAL_MODE mode ;
56+ ULONG auth_package_id ;
57+ NTSTATUS ret , subStatus ;
58+ KERB_S4U_LOGON * s4u_logon = NULL ;
59+ size_t logon_info_size ;
60+ LSA_STRING logon_process_name , auth_package_name , originName ;
61+ TOKEN_SOURCE sourceContext ;
62+ PKERB_INTERACTIVE_PROFILE pProfile = NULL ;
63+ LUID logonId ;
64+ QUOTA_LIMITS quotas ;
65+ DWORD cbProfile ;
66+
67+ InitLsaString (& logon_process_name , "ssh-agent" );
68+ InitLsaString (& auth_package_name , MICROSOFT_KERBEROS_NAME_A );
69+ //InitLsaString(&auth_package_name, "Negotiate");
70+ InitLsaString (& originName , "sshd" );
71+ if (ret = LsaRegisterLogonProcess (& logon_process_name , & lsa_handle , & mode ) != STATUS_SUCCESS )
72+ goto done ;
73+
74+ if (ret = LsaLookupAuthenticationPackage (lsa_handle , & auth_package_name , & auth_package_id ) != STATUS_SUCCESS )
75+ goto done ;
76+
77+ logon_info_size = sizeof (KERB_S4U_LOGON );
78+ logon_info_size += (wcslen (user ) * 2 + 2 );
79+ s4u_logon = malloc (logon_info_size );
80+ if (s4u_logon == NULL )
81+ goto done ;
82+
83+ s4u_logon -> MessageType = KerbS4ULogon ;
84+ s4u_logon -> Flags = 0 ;
85+ s4u_logon -> ClientUpn .Length = wcslen (user ) * 2 ;
86+ s4u_logon -> ClientUpn .MaximumLength = s4u_logon -> ClientUpn .Length ;
87+ s4u_logon -> ClientUpn .Buffer = (WCHAR * )(s4u_logon + 1 );
88+ memcpy (s4u_logon -> ClientUpn .Buffer , user , s4u_logon -> ClientUpn .Length + 2 );
89+ s4u_logon -> ClientRealm .Length = 0 ;
90+ s4u_logon -> ClientRealm .MaximumLength = 0 ;
91+ s4u_logon -> ClientRealm .Buffer = 0 ;
92+
93+ memcpy (sourceContext .SourceName ,".Jobs " , sizeof (sourceContext .SourceName ));
94+
95+ if (AllocateLocallyUniqueId (& sourceContext .SourceIdentifier ) != TRUE)
96+ goto done ;
97+
98+ if (ret = LsaLogonUser (lsa_handle ,
99+ & originName ,
100+ Network ,
101+ auth_package_id ,
102+ s4u_logon ,
103+ logon_info_size ,
104+ NULL ,
105+ & sourceContext ,
106+ (PVOID * )& pProfile ,
107+ & cbProfile ,
108+ & logonId ,
109+ & token ,
110+ & quotas ,
111+ & subStatus ) != STATUS_SUCCESS )
112+ goto done ;
113+
114+ done :
115+ if (lsa_handle )
98116 LsaDeregisterLogonProcess (lsa_handle );
99- break ;
117+ if (s4u_logon )
118+ free (s4u_logon );
119+ if (pProfile )
120+ LsaFreeReturnBuffer (pProfile );
121+
122+ return token ;
123+ }
124+
125+ #define AUTH_REQUEST "keyauthenticate"
126+ #define MAX_USER_NAME_LEN 255 + 255
127+
128+ int process_authagent_request (struct sshbuf * request , struct sshbuf * response , struct agent_connection * con ) {
129+ int r = 0 ;
130+ char * opn , key_blob , user , sig , blob ;
131+ size_t opn_len , key_blob_len , user_len , sig_len , blob_len ;
132+ struct sshkey * key = NULL ;
133+ HANDLE token = NULL , dup_token = NULL ;
134+ wchar_t wuser [MAX_USER_NAME_LEN ];
135+ PWSTR wuser_home = NULL ;
136+
137+ user = NULL ;
138+ if ((r = sshbuf_get_string_direct (request , & opn , & opn_len )) != 0 ||
139+ (r = sshbuf_get_string_direct (request , & key_blob , & key_blob_len )) != 0 ||
140+ (r = sshbuf_get_cstring (request , & user , & user_len )) != 0 ||
141+ (r = sshbuf_get_string_direct (request , & sig , & sig_len )) != 0 ||
142+ (r = sshbuf_get_string_direct (request , & blob , & blob_len )) != 0 ||
143+ (r = sshkey_from_blob (key_blob , key_blob_len , & key )) != 0 )
144+ goto done ;
145+
146+ if ((opn_len != strlen (AUTH_REQUEST )) || (memcmp (opn , AUTH_REQUEST , opn_len ) != 0 )) {
147+ r = EINVAL ;
148+ goto done ;
149+ }
150+
151+ if (0 == MultiByteToWideChar (CP_UTF8 , 0 , user , user_len + 1 , wuser , MAX_USER_NAME_LEN ) {
152+ r = GetLastError ();
153+ goto done ;
154+ }
155+
156+ if ((token = generate_user_token (wuser )) == 0 ) {
157+ r = EINVAL ;
158+ goto done ;
100159 }
101- return -1 ;
160+
161+ done :
162+ if (user )
163+ free (user );
164+ if (key )
165+ sshkey_free (key );
166+ if (token )
167+ CloseHandle (token );
168+ if (wuser_home )
169+ CoTaskMemFree (wuser_home );
170+ return r ;
102171}
0 commit comments