]>
Commit | Line | Data |
---|---|---|
3e5d7cdf | 1 | /* |
2 | * ----------------------------------------------------------------------------- | |
3 | * | |
4 | * Author: Markus Moeller (markus_moeller at compuserve.com) | |
5 | * | |
6 | * Copyright (C) 2007 Markus Moeller. 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 | * | |
ba4fe07c AJ |
22 | * As a special exemption, M Moeller gives permission to link this program |
23 | * with MIT, Heimdal or other GSS/Kerberos libraries, and distribute | |
24 | * the resulting executable, without including the source code for | |
25 | * the Libraries in the source distribution. | |
26 | * | |
3e5d7cdf | 27 | * ----------------------------------------------------------------------------- |
28 | */ | |
29 | /* | |
30 | * Hosted at http://sourceforge.net/projects/squidkerbauth | |
31 | */ | |
32 | #include <string.h> | |
33 | #include <stdio.h> | |
34 | #include <stdlib.h> | |
35 | #include <netdb.h> | |
36 | #include <unistd.h> | |
37 | #include <time.h> | |
38 | #include <sys/time.h> | |
39 | ||
ba4fe07c AJ |
40 | #include "config.h" |
41 | ||
42 | #ifdef HAVE_SQUID | |
43 | #ifdef PACKAGE | |
44 | #undef PACKAGE | |
45 | #endif | |
46 | #ifdef PACKAGE_BUGREPORT | |
47 | #undef PACKAGE_BUGREPORT | |
48 | #endif | |
49 | #ifdef PACKAGE_NAME | |
50 | #undef PACKAGE_NAME | |
51 | #endif | |
52 | #ifdef PACKAGE_STRING | |
53 | #undef PACKAGE_STRING | |
54 | #endif | |
55 | #ifdef PACKAGE_TARNAME | |
56 | #undef PACKAGE_TARNAME | |
57 | #endif | |
58 | #ifdef PACKAGE_VERSION | |
59 | #undef PACKAGE_VERSION | |
60 | #endif | |
61 | #ifdef VERSION | |
62 | #undef VERSION | |
63 | #endif | |
64 | #ifdef HAVE_GETADDRINFO_H | |
102728eb | 65 | #include "getaddrinfo.h" |
ba4fe07c AJ |
66 | #endif |
67 | #ifdef HAVE_GETNAMEINFO_H | |
102728eb | 68 | #include "getnameinfo.h" |
ba4fe07c AJ |
69 | #endif |
70 | #ifdef HAVE_UTIL_H | |
71 | #include "util.h" | |
72 | #endif | |
73 | #ifdef PACKAGE | |
74 | #undef PACKAGE | |
75 | #endif | |
76 | #ifdef PACKAGE_BUGREPORT | |
77 | #undef PACKAGE_BUGREPORT | |
78 | #endif | |
79 | #ifdef PACKAGE_NAME | |
80 | #undef PACKAGE_NAME | |
81 | #endif | |
82 | #ifdef PACKAGE_STRING | |
83 | #undef PACKAGE_STRING | |
84 | #endif | |
85 | #ifdef PACKAGE_TARNAME | |
86 | #undef PACKAGE_TARNAME | |
87 | #endif | |
88 | #ifdef PACKAGE_VERSION | |
89 | #undef PACKAGE_VERSION | |
90 | #endif | |
91 | #ifdef VERSION | |
92 | #undef VERSION | |
93 | #endif | |
94 | /* | |
95 | * Reset varibles | |
96 | */ | |
97 | #include "config.h" | |
98 | #endif | |
99 | #if !defined(HAVE_DECL_XGETADDRINFO) || !HAVE_DECL_XGETADDRINFO | |
100 | #define xgetaddrinfo getaddrinfo | |
101 | #endif | |
102 | #if !defined(HAVE_DECL_XFREEADDRINFO) || !HAVE_DECL_XFREEADDRINFO | |
103 | #define xfreeaddrinfo freeaddrinfo | |
104 | #endif | |
105 | #if !defined(HAVE_DECL_XGAI_STRERROR) || !HAVE_DECL_XGAI_STRERROR | |
106 | #define xgai_strerror gai_strerror | |
107 | #endif | |
108 | #if !defined(HAVE_DECL_XGETNAMEINFO) || !HAVE_DECL_XGETNAMEINFO | |
109 | #define xgetnameinfo getnameinfo | |
110 | #endif | |
111 | #if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC | |
112 | #define xmalloc malloc | |
113 | #endif | |
114 | #if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP | |
115 | #define xstrdup strdup | |
116 | #endif | |
117 | #if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE | |
118 | #define xfree free | |
119 | #endif | |
102728eb | 120 | |
3e5d7cdf | 121 | #include "base64.h" |
122 | #ifndef HAVE_SPNEGO | |
123 | #include "spnegohelp.h" | |
124 | #endif | |
125 | ||
3e5d7cdf | 126 | #define PROGRAM "squid_kerb_auth" |
127 | ||
ba4fe07c AJ |
128 | |
129 | #ifndef MAX_AUTHTOKEN_LEN | |
130 | #define MAX_AUTHTOKEN_LEN 65535 | |
3e5d7cdf | 131 | #endif |
132 | ||
ba4fe07c | 133 | int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log); |
3e5d7cdf | 134 | char *gethost_name(void); |
135 | static const char *LogTime(void); | |
136 | ||
137 | static const unsigned char ntlmProtocol [] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0}; | |
138 | ||
139 | static const char *LogTime() | |
140 | { | |
141 | struct tm *tm; | |
142 | struct timeval now; | |
143 | static time_t last_t = 0; | |
144 | static char buf[128]; | |
145 | ||
146 | gettimeofday(&now, NULL); | |
147 | if (now.tv_sec != last_t) { | |
ba4fe07c | 148 | tm = localtime((time_t *)&now.tv_sec); |
3e5d7cdf | 149 | strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); |
150 | last_t = now.tv_sec; | |
151 | } | |
152 | return buf; | |
153 | } | |
154 | ||
155 | char *gethost_name(void) { | |
ba4fe07c | 156 | char hostname[sysconf(_SC_HOST_NAME_MAX)]; |
3e5d7cdf | 157 | struct addrinfo *hres=NULL, *hres_list; |
158 | int rc,count; | |
159 | ||
ba4fe07c | 160 | rc = gethostname(hostname,sysconf(_SC_HOST_NAME_MAX)); |
3e5d7cdf | 161 | if (rc) |
162 | { | |
163 | fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname); | |
164 | return NULL; | |
165 | } | |
cc192b50 | 166 | rc = xgetaddrinfo(hostname,NULL,NULL,&hres); |
3e5d7cdf | 167 | if (rc != 0) { |
cc192b50 | 168 | fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc)); |
3e5d7cdf | 169 | return NULL; |
170 | } | |
171 | hres_list=hres; | |
172 | count=0; | |
173 | while (hres_list) { | |
174 | count++; | |
175 | hres_list=hres_list->ai_next; | |
176 | } | |
ba4fe07c | 177 | rc = xgetnameinfo (hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0); |
3e5d7cdf | 178 | if (rc != 0) { |
cc192b50 | 179 | fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc)); |
180 | xfreeaddrinfo(hres); | |
3e5d7cdf | 181 | return NULL ; |
182 | } | |
183 | ||
cc192b50 | 184 | xfreeaddrinfo(hres); |
ba4fe07c AJ |
185 | hostname[sysconf(_SC_HOST_NAME_MAX)-1]='\0'; |
186 | return(xstrdup(hostname)); | |
3e5d7cdf | 187 | } |
188 | ||
ba4fe07c | 189 | int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log) { |
3e5d7cdf | 190 | if (GSS_ERROR(major_status)) { |
191 | OM_uint32 maj_stat,min_stat; | |
192 | OM_uint32 msg_ctx = 0; | |
193 | gss_buffer_desc status_string; | |
194 | char buf[1024]; | |
195 | size_t len; | |
196 | ||
197 | len = 0; | |
198 | msg_ctx = 0; | |
199 | while (!msg_ctx) { | |
200 | /* convert major status code (GSS-API error) to text */ | |
201 | maj_stat = gss_display_status(&min_stat, major_status, | |
202 | GSS_C_GSS_CODE, | |
203 | GSS_C_NULL_OID, | |
204 | &msg_ctx, &status_string); | |
205 | if (maj_stat == GSS_S_COMPLETE) { | |
206 | if (sizeof(buf) > len + status_string.length + 1) { | |
207 | sprintf(buf+len, "%s", (char*) status_string.value); | |
208 | len += status_string.length; | |
209 | } | |
210 | gss_release_buffer(&min_stat, &status_string); | |
211 | break; | |
212 | } | |
213 | gss_release_buffer(&min_stat, &status_string); | |
214 | } | |
215 | if (sizeof(buf) > len + 2) { | |
216 | sprintf(buf+len, "%s", ". "); | |
217 | len += 2; | |
218 | } | |
219 | msg_ctx = 0; | |
220 | while (!msg_ctx) { | |
221 | /* convert minor status code (underlying routine error) to text */ | |
222 | maj_stat = gss_display_status(&min_stat, minor_status, | |
223 | GSS_C_MECH_CODE, | |
224 | GSS_C_NULL_OID, | |
225 | &msg_ctx, &status_string); | |
226 | if (maj_stat == GSS_S_COMPLETE) { | |
227 | if (sizeof(buf) > len + status_string.length ) { | |
228 | sprintf(buf+len, "%s", (char*) status_string.value); | |
229 | len += status_string.length; | |
230 | } | |
231 | gss_release_buffer(&min_stat, &status_string); | |
232 | break; | |
233 | } | |
234 | gss_release_buffer(&min_stat, &status_string); | |
235 | } | |
ba4fe07c | 236 | if (debug) |
3e5d7cdf | 237 | fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf); |
ba4fe07c AJ |
238 | fprintf(stdout, "BH %s failed: %s\n",function, buf); |
239 | if (log) | |
3e5d7cdf | 240 | fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(), PROGRAM); |
241 | return(1); | |
242 | } | |
243 | return(0); | |
244 | } | |
245 | ||
ba4fe07c AJ |
246 | |
247 | ||
3e5d7cdf | 248 | int main(int argc, char * const argv[]) |
249 | { | |
94fd8c3a | 250 | char buf[MAX_AUTHTOKEN_LEN]; |
3e5d7cdf | 251 | char *c; |
252 | int length=0; | |
253 | static int err=0; | |
ba4fe07c AJ |
254 | int opt, debug=0, log=0; |
255 | #ifndef HAVE_SPNEGO | |
256 | int rc; | |
257 | #endif | |
3e5d7cdf | 258 | OM_uint32 ret_flags=0, spnego_flag=0; |
259 | char *service_name=(char *)"HTTP",*host_name=NULL; | |
260 | char *token = NULL; | |
261 | char *service_principal = NULL; | |
262 | OM_uint32 major_status, minor_status; | |
263 | gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; | |
264 | gss_name_t client_name = GSS_C_NO_NAME; | |
265 | gss_name_t server_name = GSS_C_NO_NAME; | |
266 | gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL; | |
3e5d7cdf | 267 | gss_buffer_desc service = GSS_C_EMPTY_BUFFER; |
268 | gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | |
269 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | |
270 | const unsigned char *kerberosToken = NULL; | |
ba4fe07c | 271 | #ifndef HAVE_SPNEGO |
3e5d7cdf | 272 | size_t kerberosTokenLength = 0; |
ba4fe07c | 273 | #endif |
3e5d7cdf | 274 | const unsigned char *spnegoToken = NULL ; |
275 | size_t spnegoTokenLength = 0; | |
276 | ||
277 | setbuf(stdout,NULL); | |
278 | setbuf(stdin,NULL); | |
279 | ||
280 | while (-1 != (opt = getopt(argc, argv, "dis:h"))) { | |
281 | switch (opt) { | |
282 | case 'd': | |
283 | debug = 1; | |
284 | break; | |
285 | case 'i': | |
ba4fe07c | 286 | log = 1; |
3e5d7cdf | 287 | break; |
288 | case 's': | |
ba4fe07c | 289 | service_principal = xstrdup(optarg); |
3e5d7cdf | 290 | break; |
291 | case 'h': | |
ba4fe07c AJ |
292 | fprintf(stderr, "Usage: \n"); |
293 | fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n"); | |
294 | fprintf(stderr, "-d full debug\n"); | |
295 | fprintf(stderr, "-i informational messages\n"); | |
296 | fprintf(stderr, "-s service principal name\n"); | |
297 | fprintf(stderr, "-h help\n"); | |
298 | fprintf(stderr, "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n"); | |
299 | fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n"); | |
300 | exit(0); | |
3e5d7cdf | 301 | default: |
302 | fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt); | |
303 | } | |
304 | } | |
305 | ||
ba4fe07c AJ |
306 | if (debug) |
307 | fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM, VERSION); | |
3e5d7cdf | 308 | if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) { |
309 | service.value = service_principal; | |
310 | service.length = strlen((char *)service.value); | |
311 | } else { | |
312 | host_name=gethost_name(); | |
313 | if ( !host_name ) { | |
314 | fprintf(stderr, "%s| %s: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM); | |
ba4fe07c | 315 | fprintf(stdout, "BH hostname error\n"); |
3e5d7cdf | 316 | exit(-1); |
317 | } | |
ba4fe07c | 318 | service.value = xmalloc(strlen(service_name)+strlen(host_name)+2); |
3e5d7cdf | 319 | snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name); |
320 | service.length = strlen((char *)service.value); | |
321 | } | |
322 | ||
323 | while (1) { | |
324 | if (fgets(buf, sizeof(buf)-1, stdin) == NULL) { | |
325 | if (ferror(stdin)) { | |
326 | if (debug) | |
327 | fprintf(stderr, "%s| %s: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin), | |
328 | strerror(ferror(stdin))); | |
329 | ||
ba4fe07c | 330 | fprintf(stdout, "BH input error\n"); |
3e5d7cdf | 331 | exit(1); /* BIIG buffer */ |
332 | } | |
ba4fe07c | 333 | fprintf(stdout, "BH input error\n"); |
3e5d7cdf | 334 | exit(0); |
335 | } | |
336 | ||
337 | c=memchr(buf,'\n',sizeof(buf)-1); | |
338 | if (c) { | |
339 | *c = '\0'; | |
340 | length = c-buf; | |
341 | } else { | |
342 | err = 1; | |
343 | } | |
344 | if (err) { | |
345 | if (debug) | |
346 | fprintf(stderr, "%s| %s: Oversized message\n", LogTime(), PROGRAM); | |
ba4fe07c | 347 | fprintf(stdout, "BH Oversized message\n"); |
3e5d7cdf | 348 | err = 0; |
349 | continue; | |
350 | } | |
351 | ||
352 | if (debug) | |
ba4fe07c | 353 | fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf,length); |
3e5d7cdf | 354 | |
355 | if (buf[0] == '\0') { | |
356 | if (debug) | |
357 | fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), PROGRAM); | |
ba4fe07c | 358 | fprintf(stdout, "BH Invalid request\n"); |
3e5d7cdf | 359 | continue; |
360 | } | |
361 | ||
362 | if (strlen(buf) < 2) { | |
363 | if (debug) | |
364 | fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf); | |
ba4fe07c | 365 | fprintf(stdout, "BH Invalid request\n"); |
3e5d7cdf | 366 | continue; |
367 | } | |
368 | ||
369 | if ( !strncmp(buf, "QQ", 2) ) { | |
370 | gss_release_buffer(&minor_status, &input_token); | |
371 | gss_release_buffer(&minor_status, &output_token); | |
372 | gss_release_buffer(&minor_status, &service); | |
373 | gss_release_cred(&minor_status, &server_creds); | |
ba4fe07c AJ |
374 | if (server_name) |
375 | gss_release_name(&minor_status, &server_name); | |
376 | if (client_name) | |
377 | gss_release_name(&minor_status, &client_name); | |
378 | if (gss_context != GSS_C_NO_CONTEXT ) | |
379 | gss_delete_sec_context(&minor_status, &gss_context, NULL); | |
3e5d7cdf | 380 | if (kerberosToken) { |
381 | /* Allocated by parseNegTokenInit, but no matching free function exists.. */ | |
382 | if (!spnego_flag) | |
ba4fe07c | 383 | xfree((char *)kerberosToken); |
3e5d7cdf | 384 | kerberosToken=NULL; |
385 | } | |
386 | if (spnego_flag) { | |
387 | /* Allocated by makeNegTokenTarg, but no matching free function exists.. */ | |
388 | if (spnegoToken) | |
ba4fe07c | 389 | xfree((char *)spnegoToken); |
3e5d7cdf | 390 | spnegoToken=NULL; |
391 | } | |
392 | if (token) { | |
ba4fe07c | 393 | xfree(token); |
3e5d7cdf | 394 | token=NULL; |
395 | } | |
396 | if (host_name) { | |
ba4fe07c | 397 | xfree(host_name); |
3e5d7cdf | 398 | host_name=NULL; |
399 | } | |
ba4fe07c | 400 | fprintf(stdout, "BH quit command\n"); |
3e5d7cdf | 401 | exit(0); |
402 | } | |
403 | ||
ba4fe07c | 404 | if ( strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2) ) { |
3e5d7cdf | 405 | if (debug) |
406 | fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf); | |
ba4fe07c | 407 | fprintf(stdout, "BH Invalid request\n"); |
3e5d7cdf | 408 | continue; |
409 | } | |
410 | if ( !strncmp(buf, "YR", 2) ){ | |
411 | if (gss_context != GSS_C_NO_CONTEXT ) | |
412 | gss_delete_sec_context(&minor_status, &gss_context, NULL); | |
413 | gss_context = GSS_C_NO_CONTEXT; | |
414 | } | |
415 | ||
416 | if (strlen(buf) <= 3) { | |
417 | if (debug) | |
418 | fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf); | |
ba4fe07c | 419 | fprintf(stdout, "BH Invalid negotiate request\n"); |
3e5d7cdf | 420 | continue; |
421 | } | |
422 | ||
ba4fe07c AJ |
423 | input_token.length = ska_base64_decode_len(buf+3); |
424 | if (debug) | |
425 | fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf+3,(int)input_token.length); | |
426 | input_token.value = xmalloc(input_token.length); | |
3e5d7cdf | 427 | |
ba4fe07c | 428 | ska_base64_decode(input_token.value,buf+3,input_token.length); |
3e5d7cdf | 429 | |
430 | ||
431 | #ifndef HAVE_SPNEGO | |
432 | if (( rc=parseNegTokenInit (input_token.value, | |
433 | input_token.length, | |
434 | &kerberosToken, | |
435 | &kerberosTokenLength))!=0 ){ | |
436 | if (debug) | |
437 | fprintf(stderr, "%s| %s: parseNegTokenInit failed with rc=%d\n", LogTime(), PROGRAM, rc); | |
438 | ||
439 | /* if between 100 and 200 it might be a GSSAPI token and not a SPNEGO token */ | |
440 | if ( rc < 100 || rc > 199 ) { | |
441 | if (debug) | |
442 | fprintf(stderr, "%s| %s: Invalid GSS-SPNEGO query [%s]\n", LogTime(), PROGRAM, buf); | |
ba4fe07c | 443 | fprintf(stdout, "BH Invalid GSS-SPNEGO query\n"); |
3e5d7cdf | 444 | goto cleanup; |
445 | } | |
446 | if ((input_token.length >= sizeof ntlmProtocol + 1) && | |
447 | (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) { | |
448 | if (debug) | |
449 | fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol)); | |
ba4fe07c | 450 | fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol)); |
3e5d7cdf | 451 | goto cleanup; |
452 | } | |
ba4fe07c AJ |
453 | if (debug) |
454 | fprintf(stderr, "%s| %s: Token is possibly a GSSAPI token\n", LogTime(), PROGRAM); | |
3e5d7cdf | 455 | spnego_flag=0; |
456 | } else { | |
457 | gss_release_buffer(&minor_status, &input_token); | |
458 | input_token.length=kerberosTokenLength; | |
459 | input_token.value=(void *)kerberosToken; | |
460 | spnego_flag=1; | |
461 | } | |
462 | #else | |
463 | if ((input_token.length >= sizeof ntlmProtocol + 1) && | |
464 | (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) { | |
465 | if (debug) | |
466 | fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol)); | |
ba4fe07c | 467 | fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol)); |
3e5d7cdf | 468 | goto cleanup; |
469 | } | |
470 | #endif | |
471 | ||
472 | if ( service_principal ) { | |
473 | if ( strcasecmp(service_principal,"GSS_C_NO_NAME") ){ | |
474 | major_status = gss_import_name(&minor_status, &service, | |
475 | (gss_OID) GSS_C_NULL_OID, &server_name); | |
476 | ||
477 | } else { | |
478 | server_name = GSS_C_NO_NAME; | |
479 | major_status = GSS_S_COMPLETE; | |
480 | } | |
481 | } else { | |
482 | major_status = gss_import_name(&minor_status, &service, | |
483 | gss_nt_service_name, &server_name); | |
484 | } | |
485 | ||
ba4fe07c | 486 | if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,log) ) |
3e5d7cdf | 487 | goto cleanup; |
488 | ||
489 | major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE, | |
490 | GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, | |
491 | NULL, NULL); | |
ba4fe07c | 492 | if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,log) ) |
3e5d7cdf | 493 | goto cleanup; |
494 | ||
495 | major_status = gss_accept_sec_context(&minor_status, | |
496 | &gss_context, | |
497 | server_creds, | |
498 | &input_token, | |
499 | GSS_C_NO_CHANNEL_BINDINGS, | |
500 | &client_name, | |
501 | NULL, | |
502 | &output_token, | |
503 | &ret_flags, | |
504 | NULL, | |
ba4fe07c | 505 | NULL); |
3e5d7cdf | 506 | |
507 | ||
508 | if (output_token.length) { | |
509 | #ifndef HAVE_SPNEGO | |
510 | if (spnego_flag) { | |
511 | if ((rc=makeNegTokenTarg (output_token.value, | |
512 | output_token.length, | |
513 | &spnegoToken, | |
514 | &spnegoTokenLength))!=0 ) { | |
515 | if (debug) | |
516 | fprintf(stderr, "%s| %s: makeNegTokenTarg failed with rc=%d\n", LogTime(), PROGRAM, rc); | |
ba4fe07c | 517 | fprintf(stdout, "BH makeNegTokenTarg failed with rc=%d\n",rc); |
3e5d7cdf | 518 | goto cleanup; |
519 | } | |
520 | } else { | |
521 | spnegoToken = output_token.value; | |
522 | spnegoTokenLength = output_token.length; | |
523 | } | |
524 | #else | |
525 | spnegoToken = output_token.value; | |
526 | spnegoTokenLength = output_token.length; | |
527 | #endif | |
ba4fe07c | 528 | token = xmalloc(ska_base64_encode_len(spnegoTokenLength)); |
3e5d7cdf | 529 | if (token == NULL) { |
530 | if (debug) | |
531 | fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM); | |
ba4fe07c | 532 | fprintf(stdout, "BH Not enough memory\n"); |
3e5d7cdf | 533 | goto cleanup; |
534 | } | |
535 | ||
ba4fe07c | 536 | ska_base64_encode(token,(const char *)spnegoToken,ska_base64_encode_len(spnegoTokenLength),spnegoTokenLength); |
3e5d7cdf | 537 | |
ba4fe07c | 538 | if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) ) |
3e5d7cdf | 539 | goto cleanup; |
540 | if (major_status & GSS_S_CONTINUE_NEEDED) { | |
541 | if (debug) | |
542 | fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM); | |
543 | fprintf(stdout, "TT %s\n",token); | |
544 | goto cleanup; | |
545 | } | |
546 | gss_release_buffer(&minor_status, &output_token); | |
547 | major_status = gss_display_name(&minor_status, client_name, &output_token, | |
548 | NULL); | |
549 | ||
ba4fe07c | 550 | if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) ) |
3e5d7cdf | 551 | goto cleanup; |
552 | fprintf(stdout, "AF %s %s\n",token,(char *)output_token.value); | |
553 | if (debug) | |
554 | fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,(char *)output_token.value); | |
ba4fe07c | 555 | if (log) |
3e5d7cdf | 556 | fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value); |
557 | goto cleanup; | |
558 | } else { | |
ba4fe07c | 559 | if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) ) |
3e5d7cdf | 560 | goto cleanup; |
561 | if (major_status & GSS_S_CONTINUE_NEEDED) { | |
562 | if (debug) | |
563 | fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM); | |
ba4fe07c | 564 | fprintf(stdout, "NA %s\n",token); |
3e5d7cdf | 565 | goto cleanup; |
566 | } | |
567 | gss_release_buffer(&minor_status, &output_token); | |
568 | major_status = gss_display_name(&minor_status, client_name, &output_token, | |
569 | NULL); | |
570 | ||
ba4fe07c | 571 | if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) ) |
3e5d7cdf | 572 | goto cleanup; |
573 | /* | |
574 | * Return dummy token AA. May need an extra return tag then AF | |
575 | */ | |
576 | fprintf(stdout, "AF %s %s\n","AA==",(char *)output_token.value); | |
577 | if (debug) | |
578 | fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, "AA==", (char *)output_token.value); | |
ba4fe07c | 579 | if (log) |
3e5d7cdf | 580 | fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value); |
581 | ||
582 | cleanup: | |
583 | gss_release_buffer(&minor_status, &input_token); | |
584 | gss_release_buffer(&minor_status, &output_token); | |
585 | gss_release_cred(&minor_status, &server_creds); | |
ba4fe07c AJ |
586 | if (server_name) |
587 | gss_release_name(&minor_status, &server_name); | |
588 | if (client_name) | |
589 | gss_release_name(&minor_status, &client_name); | |
3e5d7cdf | 590 | if (kerberosToken) { |
591 | /* Allocated by parseNegTokenInit, but no matching free function exists.. */ | |
592 | if (!spnego_flag) | |
ba4fe07c | 593 | xfree((char *)kerberosToken); |
3e5d7cdf | 594 | kerberosToken=NULL; |
595 | } | |
596 | if (spnego_flag) { | |
597 | /* Allocated by makeNegTokenTarg, but no matching free function exists.. */ | |
598 | if (spnegoToken) | |
ba4fe07c | 599 | xfree((char *)spnegoToken); |
3e5d7cdf | 600 | spnegoToken=NULL; |
601 | } | |
602 | if (token) { | |
ba4fe07c | 603 | xfree(token); |
3e5d7cdf | 604 | token=NULL; |
605 | } | |
606 | continue; | |
607 | } | |
608 | } | |
609 | } |