10 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
11 AcquireCredentialsHandleA
,
12 (SEC_CHAR
*, SEC_CHAR
*, ULONG
, PLUID
,
13 PVOID
, SEC_GET_KEY_FN
, PVOID
, PCredHandle
, PTimeStamp
));
14 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
15 InitializeSecurityContextA
,
16 (PCredHandle
, PCtxtHandle
, SEC_CHAR
*, ULONG
, ULONG
,
17 ULONG
, PSecBufferDesc
, ULONG
, PCtxtHandle
,
18 PSecBufferDesc
, PULONG
, PTimeStamp
));
19 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
22 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
23 FreeCredentialsHandle
,
25 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
26 DeleteSecurityContext
,
28 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
29 QueryContextAttributesA
,
30 (PCtxtHandle
, ULONG
, PVOID
));
31 DECL_WINDOWS_FUNCTION(static, SECURITY_STATUS
,
33 (PCtxtHandle
, ULONG
, PSecBufferDesc
, ULONG
));
35 static HMODULE security_module
= NULL
;
37 typedef struct winSsh_gss_ctx
{
38 unsigned long maj_stat
;
39 unsigned long min_stat
;
40 CredHandle cred_handle
;
42 PCtxtHandle context_handle
;
47 const Ssh_gss_buf gss_mech_krb5
={9,"\x2A\x86\x48\x86\xF7\x12\x01\x02\x02"};
49 int ssh_gss_init(void)
52 return 1; /* already initialised */
54 security_module
= LoadLibrary("secur32.dll");
55 if (security_module
) {
56 GET_WINDOWS_FUNCTION(security_module
, AcquireCredentialsHandleA
);
57 GET_WINDOWS_FUNCTION(security_module
, InitializeSecurityContextA
);
58 GET_WINDOWS_FUNCTION(security_module
, FreeContextBuffer
);
59 GET_WINDOWS_FUNCTION(security_module
, FreeCredentialsHandle
);
60 GET_WINDOWS_FUNCTION(security_module
, DeleteSecurityContext
);
61 GET_WINDOWS_FUNCTION(security_module
, QueryContextAttributesA
);
62 GET_WINDOWS_FUNCTION(security_module
, MakeSignature
);
68 Ssh_gss_stat
ssh_gss_indicate_mech(Ssh_gss_buf
*mech
)
70 *mech
= gss_mech_krb5
;
75 Ssh_gss_stat
ssh_gss_import_name(char *host
, Ssh_gss_name
*srv_name
)
80 if (host
== NULL
) return SSH_GSS_FAILURE
;
82 /* copy it into form host/FQDN */
83 pStr
= dupcat("host/", host
, NULL
);
85 *srv_name
= (Ssh_gss_name
) pStr
;
90 Ssh_gss_stat
ssh_gss_acquire_cred(Ssh_gss_ctx
*ctx
)
92 winSsh_gss_ctx
*winctx
= snew(winSsh_gss_ctx
);
93 memset(winctx
, 0, sizeof(winSsh_gss_ctx
));
95 /* prepare our "wrapper" structure */
96 winctx
->maj_stat
= winctx
->min_stat
= SEC_E_OK
;
97 winctx
->context_handle
= NULL
;
99 /* Specifying no principal name here means use the credentials of
100 the current logged-in user */
102 winctx
->maj_stat
= p_AcquireCredentialsHandleA(NULL
,
104 SECPKG_CRED_OUTBOUND
,
109 &winctx
->cred_handle
,
112 if (winctx
->maj_stat
!= SEC_E_OK
) return SSH_GSS_FAILURE
;
114 *ctx
= (Ssh_gss_ctx
) winctx
;
119 Ssh_gss_stat
ssh_gss_init_sec_context(Ssh_gss_ctx
*ctx
,
120 Ssh_gss_name srv_name
,
122 Ssh_gss_buf
*recv_tok
,
123 Ssh_gss_buf
*send_tok
)
125 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) *ctx
;
126 SecBuffer wsend_tok
= {send_tok
->length
,SECBUFFER_TOKEN
,send_tok
->value
};
127 SecBuffer wrecv_tok
= {recv_tok
->length
,SECBUFFER_TOKEN
,recv_tok
->value
};
128 SecBufferDesc output_desc
={SECBUFFER_VERSION
,1,&wsend_tok
};
129 SecBufferDesc input_desc
={SECBUFFER_VERSION
,1,&wrecv_tok
};
130 unsigned long flags
=ISC_REQ_MUTUAL_AUTH
|ISC_REQ_REPLAY_DETECT
|
131 ISC_REQ_CONFIDENTIALITY
|ISC_REQ_ALLOCATE_MEMORY
;
132 unsigned long ret_flags
=0;
134 /* check if we have to delegate ... */
135 if (to_deleg
) flags
|= ISC_REQ_DELEGATE
;
136 winctx
->maj_stat
= p_InitializeSecurityContextA(&winctx
->cred_handle
,
137 winctx
->context_handle
,
141 SECURITY_NATIVE_DREP
,
149 /* prepare for the next round */
150 winctx
->context_handle
= &winctx
->context
;
151 send_tok
->value
= wsend_tok
.pvBuffer
;
152 send_tok
->length
= wsend_tok
.cbBuffer
;
154 /* check & return our status */
155 if (winctx
->maj_stat
==SEC_E_OK
) return SSH_GSS_S_COMPLETE
;
156 if (winctx
->maj_stat
==SEC_I_CONTINUE_NEEDED
) return SSH_GSS_S_CONTINUE_NEEDED
;
158 return SSH_GSS_FAILURE
;
161 Ssh_gss_stat
ssh_gss_free_tok(Ssh_gss_buf
*send_tok
)
164 if (send_tok
== NULL
) return SSH_GSS_FAILURE
;
166 /* free Windows buffer */
167 p_FreeContextBuffer(send_tok
->value
);
168 SSH_GSS_CLEAR_BUF(send_tok
);
173 Ssh_gss_stat
ssh_gss_release_cred(Ssh_gss_ctx
*ctx
)
175 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) *ctx
;
178 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
180 /* free Windows data */
181 p_FreeCredentialsHandle(&winctx
->cred_handle
);
182 p_DeleteSecurityContext(&winctx
->context
);
184 /* delete our "wrapper" structure */
186 *ctx
= (Ssh_gss_ctx
) NULL
;
192 Ssh_gss_stat
ssh_gss_release_name(Ssh_gss_name
*srv_name
)
194 char *pStr
= (char *) *srv_name
;
196 if (pStr
== NULL
) return SSH_GSS_FAILURE
;
198 *srv_name
= (Ssh_gss_name
) NULL
;
203 Ssh_gss_stat
ssh_gss_display_status(Ssh_gss_ctx ctx
, Ssh_gss_buf
*buf
)
205 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) ctx
;
208 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
210 /* decode the error code */
211 switch (winctx
->maj_stat
) {
212 case SEC_E_OK
: msg
="SSPI status OK"; break;
213 case SEC_E_INVALID_HANDLE
: msg
="The handle passed to the function"
216 case SEC_E_TARGET_UNKNOWN
: msg
="The target was not recognized."; break;
217 case SEC_E_LOGON_DENIED
: msg
="The logon failed."; break;
218 case SEC_E_INTERNAL_ERROR
: msg
="The Local Security Authority cannot"
221 case SEC_E_NO_CREDENTIALS
: msg
="No credentials are available in the"
222 " security package.";
224 case SEC_E_NO_AUTHENTICATING_AUTHORITY
:
225 msg
="No authority could be contacted for authentication."
226 "The domain name of the authenticating party could be wrong,"
227 " the domain could be unreachable, or there might have been"
228 " a trust relationship failure.";
230 case SEC_E_INSUFFICIENT_MEMORY
:
231 msg
="One or more of the SecBufferDesc structures passed as"
232 " an OUT parameter has a buffer that is too small.";
234 case SEC_E_INVALID_TOKEN
:
235 msg
="The error is due to a malformed input token, such as a"
236 " token corrupted in transit, a token"
237 " of incorrect size, or a token passed into the wrong"
238 " security package. Passing a token to"
239 " the wrong package can happen if client and server did not"
240 " negotiate the proper security package.";
243 msg
= "Internal SSPI error";
247 buf
->value
= dupstr(msg
);
248 buf
->length
= strlen(buf
->value
);
253 Ssh_gss_stat
ssh_gss_get_mic(Ssh_gss_ctx ctx
, Ssh_gss_buf
*buf
,
256 winSsh_gss_ctx
*winctx
= (winSsh_gss_ctx
*) ctx
;
257 SecPkgContext_Sizes ContextSizes
;
258 SecBufferDesc InputBufferDescriptor
;
259 SecBuffer InputSecurityToken
[2];
261 if (winctx
== NULL
) return SSH_GSS_FAILURE
;
263 winctx
->maj_stat
= 0;
265 memset(&ContextSizes
, 0, sizeof(ContextSizes
));
267 winctx
->maj_stat
= p_QueryContextAttributesA(&winctx
->context
,
271 if (winctx
->maj_stat
!= SEC_E_OK
||
272 ContextSizes
.cbMaxSignature
== 0)
273 return winctx
->maj_stat
;
275 InputBufferDescriptor
.cBuffers
= 2;
276 InputBufferDescriptor
.pBuffers
= InputSecurityToken
;
277 InputBufferDescriptor
.ulVersion
= SECBUFFER_VERSION
;
278 InputSecurityToken
[0].BufferType
= SECBUFFER_DATA
;
279 InputSecurityToken
[0].cbBuffer
= buf
->length
;
280 InputSecurityToken
[0].pvBuffer
= buf
->value
;
281 InputSecurityToken
[1].BufferType
= SECBUFFER_TOKEN
;
282 InputSecurityToken
[1].cbBuffer
= ContextSizes
.cbMaxSignature
;
283 InputSecurityToken
[1].pvBuffer
= snewn(ContextSizes
.cbMaxSignature
, char);
285 winctx
->maj_stat
= p_MakeSignature(&winctx
->context
,
287 &InputBufferDescriptor
,
290 if (winctx
->maj_stat
== SEC_E_OK
) {
291 hash
->length
= InputSecurityToken
[1].cbBuffer
;
292 hash
->value
= InputSecurityToken
[1].pvBuffer
;
295 return winctx
->maj_stat
;
298 Ssh_gss_stat
ssh_gss_free_mic(Ssh_gss_buf
*hash
)
306 /* Dummy function so this source file defines something if NO_GSSAPI
309 int ssh_gss_init(void)