]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/negotiate_auth/squid_kerb_auth/spnegohelp/spnegohelp.c
Summary: Synced with libecap, adopted pass-all-changes-through transactions
[thirdparty/squid.git] / helpers / negotiate_auth / squid_kerb_auth / spnegohelp / spnegohelp.c
1 /* -----------------------------------------------------------------------------
2 * spnegohelp.c defines RFC 2478 SPNEGO GSS-API mechanism APIs.
3 *
4 * Author: Frank Balluffi
5 *
6 * Copyright (C) 2002-2003 All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * -----------------------------------------------------------------------------
23 */
24
25 #include "spnegohelp.h"
26 #include "spnego.h"
27
28 #include <stdlib.h>
29
30 int makeNegTokenTarg (const unsigned char * kerberosToken,
31 size_t kerberosTokenLength,
32 const unsigned char ** negTokenTarg,
33 size_t * negTokenTargLength)
34 {
35 SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
36 int rc1 = 1;
37 int rc2 = SPNEGO_E_SUCCESS;
38
39 /* Check arguments. */
40
41 if (!kerberosToken ||
42 !negTokenTarg ||
43 !negTokenTargLength)
44 return 10;
45
46 /* Does IIS reply with 1.2.840.48018.1.2.2 or 1.2.840.113554.1.2.2? */
47
48 /* Does IIS always reply with accept_completed? */
49
50 /* IIS does not include a MIC. */
51
52 rc2 = spnegoCreateNegTokenTarg (spnego_mech_oid_Kerberos_V5_Legacy,
53 spnego_negresult_success,
54 (unsigned char *) kerberosToken,
55 kerberosTokenLength,
56 NULL,
57 0,
58 &hSpnegoToken);
59
60 if (rc2 != SPNEGO_E_SUCCESS)
61 {
62 rc1 = abs(rc2)+100;
63 goto cleanup;
64 }
65
66 /* Get NegTokenTarg length. */
67
68 rc2 = spnegoTokenGetBinary (hSpnegoToken,
69 NULL,
70 (unsigned long*) negTokenTargLength);
71
72 if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)
73 {
74 rc1 = abs(rc2)+200;
75 goto cleanup;
76 }
77
78 *negTokenTarg = malloc (*negTokenTargLength);
79
80 if (!*negTokenTarg)
81 {
82 rc1 = abs(rc2)+300;
83 goto cleanup;
84 }
85
86 /* Get NegTokenTarg data. */
87
88 rc2 = spnegoTokenGetBinary (hSpnegoToken,
89 (unsigned char *) *negTokenTarg,
90 (unsigned long*) negTokenTargLength);
91
92
93 if (rc2 != SPNEGO_E_SUCCESS)
94 {
95 rc1 = abs(rc2)+400;
96 goto error;
97 }
98
99 rc1 = 0;
100
101 goto cleanup;
102
103 error:
104
105 if (*negTokenTarg)
106 {
107 free ((unsigned char *) *negTokenTarg);
108 *negTokenTarg = NULL;
109 *negTokenTargLength = 0;
110 }
111
112 cleanup:
113
114 if (hSpnegoToken)
115 spnegoFreeData (hSpnegoToken);
116
117 LOG(("makeNegTokenTarg returned %d\n",rc1));
118 return rc1;
119 }
120
121 int parseNegTokenInit (const unsigned char * negTokenInit,
122 size_t negTokenInitLength,
123 const unsigned char ** kerberosToken,
124 size_t * kerberosTokenLength)
125 {
126 SPNEGO_TOKEN_HANDLE hSpnegoToken = NULL;
127 int pindex = -1;
128 int rc1 = 1;
129 int rc2 = SPNEGO_E_SUCCESS;
130 unsigned char reqFlags = 0;
131 int tokenType = 0;
132
133 /* Check arguments. */
134
135 if (!negTokenInit ||
136 !kerberosToken ||
137 !kerberosTokenLength)
138 return 10;
139
140 /* Decode SPNEGO token. */
141
142 rc2 = spnegoInitFromBinary ((unsigned char *) negTokenInit,
143 negTokenInitLength,
144 &hSpnegoToken);
145
146 if (rc2 != SPNEGO_E_SUCCESS)
147 {
148 rc1 = abs(rc2)+100;
149 goto cleanup;
150 }
151
152 /* Check for negTokenInit choice. */
153
154 rc2 = spnegoGetTokenType (hSpnegoToken,
155 &tokenType);
156
157 if (rc2 != SPNEGO_E_SUCCESS)
158 {
159 rc1 = abs(rc2)+200;
160 goto cleanup;
161 }
162
163 if (tokenType != SPNEGO_TOKEN_INIT)
164 {
165 rc1 = abs(rc2)+300;
166 goto cleanup;
167 }
168
169 /*
170 Check that first mechType is 1.2.840.113554.1.2.2 or 1.2.840.48018.1.2.2.
171 */
172
173 /*
174 IE seems to reply with 1.2.840.48018.1.2.2 and then 1.2.840.113554.1.2.2.
175 */
176
177 rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,
178 spnego_mech_oid_Kerberos_V5_Legacy,
179 &pindex);
180
181 if (rc2 != SPNEGO_E_SUCCESS ||
182 pindex != 0)
183 {
184 rc2 = spnegoIsMechTypeAvailable (hSpnegoToken,
185 spnego_mech_oid_Kerberos_V5,
186 &pindex);
187
188 if (rc2 != SPNEGO_E_SUCCESS ||
189 pindex != 0)
190 {
191 rc1 = abs(rc2)+400;
192 goto cleanup;
193 }
194 }
195
196 /* Check for no reqFlags. */
197
198 /* Does IE ever send reqFlags? */
199
200 rc2 = spnegoGetContextFlags (hSpnegoToken,
201 &reqFlags);
202
203 if (rc2 == SPNEGO_E_SUCCESS)
204 {
205 rc1 = abs(rc2)+500;
206 goto cleanup;
207 }
208
209 /* Get mechanism token length. */
210
211 rc2 = spnegoGetMechToken (hSpnegoToken,
212 NULL,
213 (unsigned long*) kerberosTokenLength);
214
215 if (rc2 != SPNEGO_E_BUFFER_TOO_SMALL)
216 {
217 rc1 = abs(rc2)+600;
218 goto cleanup;
219 }
220
221 *kerberosToken = malloc (*kerberosTokenLength);
222
223 if (!*kerberosToken)
224 {
225 rc1 = abs(rc2)+700;
226 goto cleanup;
227 }
228
229 /* Get mechanism token data. */
230
231 rc2 = spnegoGetMechToken (hSpnegoToken,
232 (unsigned char *) *kerberosToken,
233 (unsigned long*) kerberosTokenLength);
234
235 if (rc2 != SPNEGO_E_SUCCESS)
236 {
237 rc1 = abs(rc2)+800;
238 goto error;
239 }
240
241 /* According to Microsoft, IE does not send a MIC. */
242
243 rc1 = 0;
244
245 goto cleanup;
246
247 error:
248
249 if (*kerberosToken)
250 {
251 free ((unsigned char *) *kerberosToken);
252 *kerberosToken = NULL;
253 *kerberosTokenLength = 0;
254 }
255
256 cleanup:
257
258 if (hSpnegoToken)
259 spnegoFreeData (hSpnegoToken);
260
261 LOG(("parseNegTokenInit returned %d\n",rc1));
262 return rc1;
263 }