/src/gss-ntlmssp/src/gss_signseal.c
Line | Count | Source |
1 | | /* Copyright 2013 Simo Sorce <simo@samba.org>, see COPYING for license */ |
2 | | |
3 | | #include <errno.h> |
4 | | #include <stdlib.h> |
5 | | #include <string.h> |
6 | | #include <time.h> |
7 | | |
8 | | #include "gssapi_ntlmssp.h" |
9 | | #include "gss_ntlmssp.h" |
10 | | |
11 | | uint32_t gssntlm_get_mic(uint32_t *minor_status, |
12 | | gss_ctx_id_t context_handle, |
13 | | gss_qop_t qop_req, |
14 | | gss_buffer_t message_buffer, |
15 | | gss_buffer_t message_token) |
16 | 0 | { |
17 | 0 | struct gssntlm_ctx *ctx; |
18 | 0 | struct ntlm_buffer message; |
19 | 0 | struct ntlm_buffer signature; |
20 | 0 | uint32_t retmaj, retmin; |
21 | |
|
22 | 0 | ctx = (struct gssntlm_ctx *)context_handle; |
23 | 0 | retmaj = gssntlm_context_is_valid(ctx, NULL); |
24 | 0 | if (retmaj != GSS_S_COMPLETE) { |
25 | 0 | return GSSERRS(ERR_BADCTX, retmaj); |
26 | 0 | } |
27 | 0 | if (qop_req != GSS_C_QOP_DEFAULT) { |
28 | 0 | return GSSERRS(ERR_BADARG, GSS_S_BAD_QOP); |
29 | 0 | } |
30 | 0 | if (!message_buffer->value || message_buffer->length == 0) { |
31 | 0 | return GSSERRS(ERR_BADARG, GSS_S_CALL_INACCESSIBLE_READ); |
32 | 0 | } |
33 | | |
34 | 0 | message_token->value = malloc(NTLM_SIGNATURE_SIZE); |
35 | 0 | if (!message_token->value) { |
36 | 0 | return GSSERRS(ENOMEM, GSS_S_FAILURE); |
37 | 0 | } |
38 | 0 | message_token->length = NTLM_SIGNATURE_SIZE; |
39 | |
|
40 | 0 | message.data = message_buffer->value; |
41 | 0 | message.length = message_buffer->length; |
42 | 0 | signature.data = message_token->value; |
43 | 0 | signature.length = message_token->length; |
44 | 0 | retmin = ntlm_sign(ctx->neg_flags, NTLM_SEND, |
45 | 0 | &ctx->crypto_state, |
46 | 0 | &message, &signature); |
47 | 0 | if (retmin) { |
48 | 0 | safefree(message_token->value); |
49 | 0 | return GSSERRS(retmin, GSS_S_FAILURE); |
50 | 0 | } |
51 | | |
52 | 0 | return GSSERRS(0, GSS_S_COMPLETE); |
53 | 0 | } |
54 | | |
55 | | uint32_t gssntlm_verify_mic(uint32_t *minor_status, |
56 | | gss_ctx_id_t context_handle, |
57 | | gss_buffer_t message_buffer, |
58 | | gss_buffer_t message_token, |
59 | | gss_qop_t *qop_state) |
60 | 0 | { |
61 | 0 | struct gssntlm_ctx *ctx; |
62 | 0 | struct ntlm_buffer message; |
63 | 0 | uint8_t token[16]; |
64 | 0 | struct ntlm_buffer signature = { token, NTLM_SIGNATURE_SIZE }; |
65 | 0 | uint32_t retmaj, retmin; |
66 | |
|
67 | 0 | ctx = (struct gssntlm_ctx *)context_handle; |
68 | 0 | retmaj = gssntlm_context_is_valid(ctx, NULL); |
69 | 0 | if (retmaj != GSS_S_COMPLETE) { |
70 | 0 | return GSSERRS(ERR_BADCTX, retmaj); |
71 | 0 | } |
72 | 0 | if (!message_buffer->value || message_buffer->length == 0) { |
73 | 0 | return GSSERRS(ERR_NOARG, GSS_S_CALL_INACCESSIBLE_READ); |
74 | 0 | } |
75 | 0 | if (qop_state) { |
76 | 0 | *qop_state = GSS_C_QOP_DEFAULT; |
77 | 0 | } |
78 | |
|
79 | 0 | message.data = message_buffer->value; |
80 | 0 | message.length = message_buffer->length; |
81 | 0 | retmin = ntlm_sign(ctx->neg_flags, NTLM_RECV, |
82 | 0 | &ctx->crypto_state, |
83 | 0 | &message, &signature); |
84 | 0 | if (retmin) { |
85 | 0 | return GSSERRS(retmin, GSS_S_FAILURE); |
86 | 0 | } |
87 | | |
88 | 0 | if (memcmp(signature.data, |
89 | 0 | message_token->value, NTLM_SIGNATURE_SIZE) != 0) { |
90 | 0 | return GSSERRS(0, GSS_S_BAD_SIG); |
91 | 0 | } |
92 | | |
93 | 0 | return GSSERRS(0, GSS_S_COMPLETE); |
94 | 0 | } |
95 | | |
96 | | uint32_t gssntlm_wrap(uint32_t *minor_status, |
97 | | gss_ctx_id_t context_handle, |
98 | | int conf_req_flag, |
99 | | gss_qop_t qop_req, |
100 | | gss_buffer_t input_message_buffer, |
101 | | int *conf_state, |
102 | | gss_buffer_t output_message_buffer) |
103 | 0 | { |
104 | 0 | struct gssntlm_ctx *ctx; |
105 | 0 | struct ntlm_buffer message; |
106 | 0 | struct ntlm_buffer output; |
107 | 0 | struct ntlm_buffer signature; |
108 | 0 | uint32_t retmaj, retmin; |
109 | |
|
110 | 0 | ctx = (struct gssntlm_ctx *)context_handle; |
111 | 0 | retmaj = gssntlm_context_is_valid(ctx, NULL); |
112 | 0 | if (retmaj != GSS_S_COMPLETE) { |
113 | 0 | return GSSERRS(ERR_BADCTX, retmaj); |
114 | 0 | } |
115 | 0 | if (qop_req != GSS_C_QOP_DEFAULT) { |
116 | 0 | return GSSERRS(ERR_BADARG, GSS_S_BAD_QOP); |
117 | 0 | } |
118 | 0 | if (!input_message_buffer->value || input_message_buffer->length == 0) { |
119 | 0 | return GSSERRS(ERR_BADARG, GSS_S_CALL_INACCESSIBLE_READ); |
120 | 0 | } |
121 | 0 | if (conf_state) { |
122 | 0 | *conf_state = 0; |
123 | 0 | } |
124 | |
|
125 | 0 | if (conf_req_flag == 0) { |
126 | | /* ignore, always seal */ |
127 | 0 | } |
128 | |
|
129 | 0 | output_message_buffer->length = |
130 | 0 | input_message_buffer->length + NTLM_SIGNATURE_SIZE; |
131 | 0 | output_message_buffer->value = malloc(output_message_buffer->length); |
132 | 0 | if (!output_message_buffer->value) { |
133 | 0 | return GSSERRS(ENOMEM, GSS_S_FAILURE); |
134 | 0 | } |
135 | | |
136 | 0 | message.data = input_message_buffer->value; |
137 | 0 | message.length = input_message_buffer->length; |
138 | 0 | signature.data = output_message_buffer->value; |
139 | 0 | signature.length = NTLM_SIGNATURE_SIZE; |
140 | 0 | output.data = (uint8_t *)output_message_buffer->value + NTLM_SIGNATURE_SIZE; |
141 | 0 | output.length = input_message_buffer->length; |
142 | 0 | retmin = ntlm_seal(ctx->neg_flags, &ctx->crypto_state, |
143 | 0 | &message, &output, &signature); |
144 | 0 | if (retmin) { |
145 | 0 | safefree(output_message_buffer->value); |
146 | 0 | return GSSERRS(retmin, GSS_S_FAILURE); |
147 | 0 | } |
148 | | |
149 | 0 | if (conf_state) { |
150 | 0 | *conf_state = 1; |
151 | 0 | } |
152 | 0 | return GSSERRS(0, GSS_S_COMPLETE); |
153 | 0 | } |
154 | | |
155 | | uint32_t gssntlm_unwrap(uint32_t *minor_status, |
156 | | gss_ctx_id_t context_handle, |
157 | | gss_buffer_t input_message_buffer, |
158 | | gss_buffer_t output_message_buffer, |
159 | | int *conf_state, |
160 | | gss_qop_t *qop_state) |
161 | 0 | { |
162 | 0 | struct gssntlm_ctx *ctx; |
163 | 0 | struct ntlm_buffer message; |
164 | 0 | struct ntlm_buffer output; |
165 | 0 | uint8_t sig[16]; |
166 | 0 | struct ntlm_buffer signature = { sig, NTLM_SIGNATURE_SIZE }; |
167 | 0 | uint32_t retmaj, retmin; |
168 | |
|
169 | 0 | ctx = (struct gssntlm_ctx *)context_handle; |
170 | 0 | retmaj = gssntlm_context_is_valid(ctx, NULL); |
171 | 0 | if (retmaj != GSS_S_COMPLETE) { |
172 | 0 | return GSSERRS(ERR_BADCTX, retmaj); |
173 | 0 | } |
174 | 0 | if (!input_message_buffer->value || input_message_buffer->length == 0) { |
175 | 0 | return GSSERRS(ERR_BADARG, GSS_S_CALL_INACCESSIBLE_READ); |
176 | 0 | } |
177 | 0 | if (conf_state) { |
178 | 0 | *conf_state = 0; |
179 | 0 | } |
180 | 0 | if (qop_state) { |
181 | 0 | *qop_state = GSS_C_QOP_DEFAULT; |
182 | 0 | } |
183 | |
|
184 | 0 | output_message_buffer->length = |
185 | 0 | input_message_buffer->length - NTLM_SIGNATURE_SIZE; |
186 | 0 | output_message_buffer->value = malloc(output_message_buffer->length); |
187 | 0 | if (!output_message_buffer->value) { |
188 | 0 | return GSSERRS(ENOMEM, GSS_S_FAILURE); |
189 | 0 | } |
190 | | |
191 | 0 | message.data = (uint8_t *)input_message_buffer->value + NTLM_SIGNATURE_SIZE; |
192 | 0 | message.length = input_message_buffer->length - NTLM_SIGNATURE_SIZE; |
193 | 0 | output.data = output_message_buffer->value; |
194 | 0 | output.length = output_message_buffer->length; |
195 | 0 | retmin = ntlm_unseal(ctx->neg_flags, &ctx->crypto_state, |
196 | 0 | &message, &output, &signature); |
197 | 0 | if (retmin) { |
198 | 0 | safefree(output_message_buffer->value); |
199 | 0 | return GSSERRS(retmin, GSS_S_FAILURE); |
200 | 0 | } |
201 | | |
202 | 0 | if (memcmp(input_message_buffer->value, |
203 | 0 | signature.data, NTLM_SIGNATURE_SIZE) != 0) { |
204 | 0 | safefree(output_message_buffer->value); |
205 | 0 | return GSSERRS(0, GSS_S_BAD_SIG); |
206 | 0 | } |
207 | | |
208 | 0 | if (conf_state) { |
209 | 0 | *conf_state = 1; |
210 | 0 | } |
211 | 0 | return GSSERRS(0, GSS_S_COMPLETE); |
212 | 0 | } |
213 | | |
214 | | uint32_t gssntlm_wrap_size_limit(uint32_t *minor_status, |
215 | | gss_ctx_id_t context_handle, |
216 | | int conf_req_flag, |
217 | | gss_qop_t qop_req, |
218 | | uint32_t req_output_size, |
219 | | uint32_t *max_input_size) |
220 | 0 | { |
221 | 0 | struct gssntlm_ctx *ctx; |
222 | 0 | uint32_t retmaj, retmin; |
223 | |
|
224 | 0 | ctx = (struct gssntlm_ctx *)context_handle; |
225 | 0 | retmaj = gssntlm_context_is_valid(ctx, NULL); |
226 | 0 | if (retmaj != GSS_S_COMPLETE) { |
227 | 0 | return GSSERRS(ERR_BADCTX, retmaj); |
228 | 0 | } |
229 | | |
230 | 0 | if (qop_req != GSS_C_QOP_DEFAULT) { |
231 | 0 | return GSSERRS(ERR_BADARG, GSS_S_BAD_QOP); |
232 | 0 | } |
233 | | |
234 | 0 | if (req_output_size < 16) { |
235 | 0 | *max_input_size = 0; |
236 | 0 | } else { |
237 | 0 | *max_input_size = req_output_size - NTLM_SIGNATURE_SIZE; |
238 | 0 | } |
239 | |
|
240 | 0 | return GSSERRS(0, GSS_S_COMPLETE); |
241 | 0 | } |