blob: 9d218bdc7262c580e7891170de0dfe7a3f850df0 [file] [log] [blame]
Don Newton379ae252019-04-01 12:17:06 -04001//+build gssapi,windows
2
3#include "sspi_wrapper.h"
4
5static HINSTANCE sspi_secur32_dll = NULL;
6static PSecurityFunctionTable sspi_functions = NULL;
7static const LPSTR SSPI_PACKAGE_NAME = "kerberos";
8
9int sspi_init(
10)
11{
12 sspi_secur32_dll = LoadLibrary("secur32.dll");
13 if (!sspi_secur32_dll) {
14 return GetLastError();
15 }
16
17 INIT_SECURITY_INTERFACE init_security_interface = (INIT_SECURITY_INTERFACE)GetProcAddress(sspi_secur32_dll, SECURITY_ENTRYPOINT);
18 if (!init_security_interface) {
19 return -1;
20 }
21
22 sspi_functions = (*init_security_interface)();
23 if (!sspi_functions) {
24 return -2;
25 }
26
27 return SSPI_OK;
28}
29
30int sspi_client_init(
31 sspi_client_state *client,
32 char* username,
33 char* password
34)
35{
36 TimeStamp timestamp;
37
38 if (username) {
39 if (password) {
40 SEC_WINNT_AUTH_IDENTITY auth_identity;
41
42 #ifdef _UNICODE
43 auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
44 #else
45 auth_identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
46 #endif
47 auth_identity.User = (LPSTR) username;
48 auth_identity.UserLength = strlen(username);
49 auth_identity.Password = (LPSTR) password;
50 auth_identity.PasswordLength = strlen(password);
51 auth_identity.Domain = NULL;
52 auth_identity.DomainLength = 0;
53 client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, &auth_identity, NULL, NULL, &client->cred, &timestamp);
54 } else {
55 client->status = sspi_functions->AcquireCredentialsHandle(username, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, &timestamp);
56 }
57 } else {
58 client->status = sspi_functions->AcquireCredentialsHandle(NULL, SSPI_PACKAGE_NAME, SECPKG_CRED_OUTBOUND, NULL, NULL, NULL, NULL, &client->cred, &timestamp);
59 }
60
61 if (client->status != SEC_E_OK) {
62 return SSPI_ERROR;
63 }
64
65 return SSPI_OK;
66}
67
68int sspi_client_username(
69 sspi_client_state *client,
70 char** username
71)
72{
73 SecPkgCredentials_Names names;
74 client->status = sspi_functions->QueryCredentialsAttributes(&client->cred, SECPKG_CRED_ATTR_NAMES, &names);
75
76 if (client->status != SEC_E_OK) {
77 return SSPI_ERROR;
78 }
79
80 int len = strlen(names.sUserName) + 1;
81 *username = malloc(len);
82 memcpy(*username, names.sUserName, len);
83
84 sspi_functions->FreeContextBuffer(names.sUserName);
85
86 return SSPI_OK;
87}
88
89int sspi_client_negotiate(
90 sspi_client_state *client,
91 char* spn,
92 PVOID input,
93 ULONG input_length,
94 PVOID* output,
95 ULONG* output_length
96)
97{
98 SecBufferDesc inbuf;
99 SecBuffer in_bufs[1];
100 SecBufferDesc outbuf;
101 SecBuffer out_bufs[1];
102
103 if (client->has_ctx > 0) {
104 inbuf.ulVersion = SECBUFFER_VERSION;
105 inbuf.cBuffers = 1;
106 inbuf.pBuffers = in_bufs;
107 in_bufs[0].pvBuffer = input;
108 in_bufs[0].cbBuffer = input_length;
109 in_bufs[0].BufferType = SECBUFFER_TOKEN;
110 }
111
112 outbuf.ulVersion = SECBUFFER_VERSION;
113 outbuf.cBuffers = 1;
114 outbuf.pBuffers = out_bufs;
115 out_bufs[0].pvBuffer = NULL;
116 out_bufs[0].cbBuffer = 0;
117 out_bufs[0].BufferType = SECBUFFER_TOKEN;
118
119 ULONG context_attr = 0;
120
121 client->status = sspi_functions->InitializeSecurityContext(
122 &client->cred,
123 client->has_ctx > 0 ? &client->ctx : NULL,
124 (LPSTR) spn,
125 ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MUTUAL_AUTH,
126 0,
127 SECURITY_NETWORK_DREP,
128 client->has_ctx > 0 ? &inbuf : NULL,
129 0,
130 &client->ctx,
131 &outbuf,
132 &context_attr,
133 NULL);
134
135 if (client->status != SEC_E_OK && client->status != SEC_I_CONTINUE_NEEDED) {
136 return SSPI_ERROR;
137 }
138
139 client->has_ctx = 1;
140
141 *output = malloc(out_bufs[0].cbBuffer);
142 *output_length = out_bufs[0].cbBuffer;
143 memcpy(*output, out_bufs[0].pvBuffer, *output_length);
144 sspi_functions->FreeContextBuffer(out_bufs[0].pvBuffer);
145
146 if (client->status == SEC_I_CONTINUE_NEEDED) {
147 return SSPI_CONTINUE;
148 }
149
150 return SSPI_OK;
151}
152
153int sspi_client_wrap_msg(
154 sspi_client_state *client,
155 PVOID input,
156 ULONG input_length,
157 PVOID* output,
158 ULONG* output_length
159)
160{
161 SecPkgContext_Sizes sizes;
162
163 client->status = sspi_functions->QueryContextAttributes(&client->ctx, SECPKG_ATTR_SIZES, &sizes);
164 if (client->status != SEC_E_OK) {
165 return SSPI_ERROR;
166 }
167
168 char *msg = malloc((sizes.cbSecurityTrailer + input_length + sizes.cbBlockSize) * sizeof(char));
169 memcpy(&msg[sizes.cbSecurityTrailer], input, input_length);
170
171 SecBuffer wrap_bufs[3];
172 SecBufferDesc wrap_buf_desc;
173 wrap_buf_desc.cBuffers = 3;
174 wrap_buf_desc.pBuffers = wrap_bufs;
175 wrap_buf_desc.ulVersion = SECBUFFER_VERSION;
176
177 wrap_bufs[0].cbBuffer = sizes.cbSecurityTrailer;
178 wrap_bufs[0].BufferType = SECBUFFER_TOKEN;
179 wrap_bufs[0].pvBuffer = msg;
180
181 wrap_bufs[1].cbBuffer = input_length;
182 wrap_bufs[1].BufferType = SECBUFFER_DATA;
183 wrap_bufs[1].pvBuffer = msg + sizes.cbSecurityTrailer;
184
185 wrap_bufs[2].cbBuffer = sizes.cbBlockSize;
186 wrap_bufs[2].BufferType = SECBUFFER_PADDING;
187 wrap_bufs[2].pvBuffer = msg + sizes.cbSecurityTrailer + input_length;
188
189 client->status = sspi_functions->EncryptMessage(&client->ctx, SECQOP_WRAP_NO_ENCRYPT, &wrap_buf_desc, 0);
190 if (client->status != SEC_E_OK) {
191 free(msg);
192 return SSPI_ERROR;
193 }
194
195 *output_length = wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer + wrap_bufs[2].cbBuffer;
196 *output = malloc(*output_length);
197
198 memcpy(*output, wrap_bufs[0].pvBuffer, wrap_bufs[0].cbBuffer);
199 memcpy(*output + wrap_bufs[0].cbBuffer, wrap_bufs[1].pvBuffer, wrap_bufs[1].cbBuffer);
200 memcpy(*output + wrap_bufs[0].cbBuffer + wrap_bufs[1].cbBuffer, wrap_bufs[2].pvBuffer, wrap_bufs[2].cbBuffer);
201
202 free(msg);
203
204 return SSPI_OK;
205}
206
207int sspi_client_destroy(
208 sspi_client_state *client
209)
210{
211 if (client->has_ctx > 0) {
212 sspi_functions->DeleteSecurityContext(&client->ctx);
213 }
214
215 sspi_functions->FreeCredentialsHandle(&client->cred);
216
217 return SSPI_OK;
218}