11 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
12 AcquireCredentialsHandleA
,
13 (SEC_CHAR
*, SEC_CHAR
*, ULONG
, PLUID
,
14 PVOID
, SEC_GET_KEY_FN
, PVOID
, PCredHandle
, PTimeStamp
));
15 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
16 InitializeSecurityContextA
,
17 (PCredHandle
, PCtxtHandle
, SEC_CHAR
*, ULONG
, ULONG
,
18 ULONG
, PSecBufferDesc
, ULONG
, PCtxtHandle
,
19 PSecBufferDesc
, PULONG
, PTimeStamp
));
20 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
23 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
24 FreeCredentialsHandle
,
26 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
27 DeleteSecurityContext
,
29 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
30 QueryContextAttributesA
,
31 (PCtxtHandle
, ULONG
, PVOID
));
32 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
34 (PCtxtHandle
, ULONG
, PSecBufferDesc
, ULONG
));
36 static HMODULE security_module
= NULL
;
38 typedef struct winSsh_gss_ctx
{
39 unsigned long maj_stat
;
40 unsigned long min_stat
;
41 CredHandle cred_handle
;
43 PCtxtHandle context_handle
;
48 const Ssh_gss_buf gss_mech_krb5
={9,"\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"};
50 int ssh_gss_init(void)
53 return 1; /* already initialised */
55 security_module
= LoadLibrary("secur32.dll");
56 if (security_module
) {
57 GET_WINDOWS_FUNCTION(security_module
, AcquireCredentialsHandleA
);
58 GET_WINDOWS_FUNCTION(security_module
, InitializeSecurityContextA
);
59 GET_WINDOWS_FUNCTION(security_module
, FreeContextBuffer
);
60 GET_WINDOWS_FUNCTION(security_module
, FreeCredentialsHandle
);
61 GET_WINDOWS_FUNCTION(security_module
, DeleteSecurityContext
);
62 GET_WINDOWS_FUNCTION(security_module
, QueryContextAttributesA
);
63 GET_WINDOWS_FUNCTION(security_module
, MakeSignature
);
69 Ssh_gss_stat
ssh_gss_indicate_mech(Ssh_gss_buf
*mech
)
71 *mech
= gss_mech_krb5
;
76 Ssh_gss_stat
ssh_gss_import_name(char *host
, Ssh_gss_name
*srv_name
)
81 if (host
== NULL
) return SSH_GSS_FAILURE
;
83 /* copy it into form host/FQDN */
84 pStr
= dupcat("host/", host
, NULL
);
86 *srv_name
= (Ssh_gss_name
) pStr
;
91 Ssh_gss_stat
ssh_gss_acquire_cred(Ssh_gss_ctx
*ctx
)
93 winSsh_gss_ctx
*winctx
= snew(winSsh_gss_ctx
);
94 memset(winctx
, 0, sizeof(winSsh_gss_ctx
));
96 /* prepare our "wrapper" structure */
97 winctx
->maj_stat
= winctx
->min_stat
= SEC_E_OK
;
98 winctx
->context_handle
= NULL
;
100 /* Specifying no principal name here means use the credentials of
101 the current logged-in user */
103 winctx
->maj_stat
= p_AcquireCredentialsHandleA(NULL
,
105 SECPKG_CRED_OUTBOUND
,
110 &winctx
->cred_handle
,
113 if (winctx
->maj_stat
!= SEC_E_OK
) return SSH_GSS_FAILURE
;
115 *ctx
= (Ssh_gss_ctx
) winctx
;
120 Ssh_gss_stat
ssh_gss_init_sec_context(Ssh_gss_ctx
*ctx
,
121 Ssh_gss_name srv_name
,
123 Ssh_gss_buf
*recv_tok
,
124 Ssh_gss_buf
*send_tok
)
126 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) *ctx
;
127 SecBuffer wsend_tok
= {send_tok
->length
,SECBUFFER_TOKEN
,send_tok
->value
};
128 SecBuffer wrecv_tok
= {recv_tok
->length
,SECBUFFER_TOKEN
,recv_tok
->value
};
129 SecBufferDesc output_desc
={SECBUFFER_VERSION
,1,&wsend_tok
};
130 SecBufferDesc input_desc
={SECBUFFER_VERSION
,1,&wrecv_tok
};
131 unsigned long flags
=ISC_REQ_MUTUAL_AUTH
|ISC_REQ_REPLAY_DETECT
|
132 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_ALLOCATE_MEMORY
;
133 unsigned long ret_flags
=0;
135 /* check if we have to delegate ... */
136 if (to_deleg
) flags
|= ISC_REQ_DELEGATE
;
137 winctx
->maj_stat
= p_InitializeSecurityContextA(&winctx
->cred_handle
,
138 winctx
->context_handle
,
142 SECURITY_NATIVE_DREP
,
150 /* prepare for the next round */
151 winctx
->context_handle
= &winctx
->context
;
152 send_tok
->value
= wsend_tok
.pvBuffer
;
153 send_tok
->length
= wsend_tok
.cbBuffer
;
155 /* check & return our status */
156 if (winctx
->maj_stat
==SEC_E_OK
) return SSH_GSS_S_COMPLETE
;
157 if (winctx
->maj_stat
==SEC_I_CONTINUE_NEEDED
) return SSH_GSS_S_CONTINUE_NEEDED
;
159 return SSH_GSS_FAILURE
;
162 Ssh_gss_stat
ssh_gss_free_tok(Ssh_gss_buf
*send_tok
)
165 if (send_tok
== NULL
) return SSH_GSS_FAILURE
;
167 /* free Windows buffer */
168 p_FreeContextBuffer(send_tok
->value
);
169 SSH_GSS_CLEAR_BUF(send_tok
);
174 Ssh_gss_stat
ssh_gss_release_cred(Ssh_gss_ctx
*ctx
)
176 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) *ctx
;
179 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
181 /* free Windows data */
182 p_FreeCredentialsHandle(&winctx
->cred_handle
);
183 p_DeleteSecurityContext(&winctx
->context
);
185 /* delete our "wrapper" structure */
187 *ctx
= (Ssh_gss_ctx
) NULL
;
193 Ssh_gss_stat
ssh_gss_release_name(Ssh_gss_name
*srv_name
)
195 char *pStr
= (char *) *srv_name
;
197 if (pStr
== NULL
) return SSH_GSS_FAILURE
;
199 *srv_name
= (Ssh_gss_name
) NULL
;
204 Ssh_gss_stat
ssh_gss_display_status(Ssh_gss_ctx ctx
, Ssh_gss_buf
*buf
)
206 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) ctx
;
209 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
211 /* decode the error code */
212 switch (winctx
->maj_stat
) {
213 case SEC_E_OK
: msg
="SSPI status OK"; break;
214 case SEC_E_INVALID_HANDLE
: msg
="The handle passed to the function"
217 case SEC_E_TARGET_UNKNOWN
: msg
="The target was not recognized."; break;
218 case SEC_E_LOGON_DENIED
: msg
="The logon failed."; break;
219 case SEC_E_INTERNAL_ERROR
: msg
="The Local Security Authority cannot"
222 case SEC_E_NO_CREDENTIALS
: msg
="No credentials are available in the"
223 " security package.";
225 case SEC_E_NO_AUTHENTICATING_AUTHORITY
:
226 msg
="No authority could be contacted for authentication."
227 "The domain name of the authenticating party could be wrong,"
228 " the domain could be unreachable, or there might have been"
229 " a trust relationship failure.";
231 case SEC_E_INSUFFICIENT_MEMORY
:
232 msg
="One or more of the SecBufferDesc structures passed as"
233 " an OUT parameter has a buffer that is too small.";
235 case SEC_E_INVALID_TOKEN
:
236 msg
="The error is due to a malformed input token, such as a"
237 " token corrupted in transit, a token"
238 " of incorrect size, or a token passed into the wrong"
239 " security package. Passing a token to"
240 " the wrong package can happen if client and server did not"
241 " negotiate the proper security package.";
244 msg
= "Internal SSPI error";
248 buf
->value
= dupstr(msg
);
249 buf
->length
= strlen(buf
->value
);
254 Ssh_gss_stat
ssh_gss_get_mic(Ssh_gss_ctx ctx
, Ssh_gss_buf
*buf
,
257 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) ctx
;
258 SecPkgContext_Sizes ContextSizes
;
259 SecBufferDesc InputBufferDescriptor
;
260 SecBuffer InputSecurityToken
[2];
262 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
264 winctx
->maj_stat
= 0;
266 memset(&ContextSizes
, 0, sizeof(ContextSizes
));
268 winctx
->maj_stat
= p_QueryContextAttributesA(&winctx
->context
,
272 if (winctx
->maj_stat
!= SEC_E_OK
||
273 ContextSizes
.cbMaxSignature
== 0)
274 return winctx
->maj_stat
;
276 InputBufferDescriptor
.cBuffers
= 2;
277 InputBufferDescriptor
.pBuffers
= InputSecurityToken
;
278 InputBufferDescriptor
.ulVersion
= SECBUFFER_VERSION
;
279 InputSecurityToken
[0].BufferType
= SECBUFFER_DATA
;
280 InputSecurityToken
[0].cbBuffer
= buf
->length
;
281 InputSecurityToken
[0].pvBuffer
= buf
->value
;
282 InputSecurityToken
[1].BufferType
= SECBUFFER_TOKEN
;
283 InputSecurityToken
[1].cbBuffer
= ContextSizes
.cbMaxSignature
;
284 InputSecurityToken
[1].pvBuffer
= snewn(ContextSizes
.cbMaxSignature
, char);
286 winctx
->maj_stat
= p_MakeSignature(&winctx
->context
,
288 &InputBufferDescriptor
,
291 if (winctx
->maj_stat
== SEC_E_OK
) {
292 hash
->length
= InputSecurityToken
[1].cbBuffer
;
293 hash
->value
= InputSecurityToken
[1].pvBuffer
;
296 return winctx
->maj_stat
;
299 Ssh_gss_stat
ssh_gss_free_mic(Ssh_gss_buf
*hash
)
307 /* Dummy function so this source file defines something if NO_GSSAPI
310 int ssh_gss_init(void)