]>
Commit | Line | Data |
---|---|---|
ca02e0ec AJ |
1 | /* |
2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
ba4fe07c AJ |
9 | /* |
10 | * ----------------------------------------------------------------------------- | |
11 | * | |
12 | * Author: Markus Moeller (markus_moeller at compuserve.com) | |
13 | * | |
14 | * Copyright (C) 2007 Markus Moeller. All rights reserved. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | |
29 | * | |
30 | * ----------------------------------------------------------------------------- | |
31 | */ | |
ba4fe07c | 32 | |
f7f3304a | 33 | #include "squid.h" |
d1f95b42 | 34 | |
3ad12bda | 35 | #if HAVE_GSSAPI |
70125c34 | 36 | |
074d6a40 AJ |
37 | #include <cerrno> |
38 | #include <cstring> | |
39 | #include <ctime> | |
70125c34 | 40 | #if HAVE_NETDB_H |
ba4fe07c | 41 | #include <netdb.h> |
70125c34 AJ |
42 | #endif |
43 | #if HAVE_UNISTD_H | |
ba4fe07c | 44 | #include <unistd.h> |
70125c34 | 45 | #endif |
ba4fe07c | 46 | |
70125c34 | 47 | #include "base64.h" |
3ad12bda AJ |
48 | #include "util.h" |
49 | ||
1a22a39e MM |
50 | #if USE_HEIMDAL_KRB5 |
51 | #if HAVE_GSSAPI_GSSAPI_H | |
52 | #include <gssapi/gssapi.h> | |
53 | #elif HAVE_GSSAPI_H | |
54 | #include <gssapi.h> | |
55 | #endif | |
56 | #elif USE_GNUGSS | |
57 | #if HAVE_GSS_H | |
58 | #include <gss.h> | |
59 | #endif | |
60 | #else | |
3ad12bda AJ |
61 | #if HAVE_GSSAPI_GSSAPI_H |
62 | #include <gssapi/gssapi.h> | |
63 | #elif HAVE_GSSAPI_H | |
64 | #include <gssapi.h> | |
75a8c92e | 65 | #endif |
3ad12bda AJ |
66 | #if HAVE_GSSAPI_GSSAPI_KRB5_H |
67 | #include <gssapi/gssapi_krb5.h> | |
75a8c92e | 68 | #endif |
3ad12bda AJ |
69 | #if HAVE_GSSAPI_GSSAPI_GENERIC_H |
70 | #include <gssapi/gssapi_generic.h> | |
75a8c92e AJ |
71 | #endif |
72 | #if HAVE_GSSAPI_GSSAPI_EXT_H | |
73 | #include <gssapi/gssapi_ext.h> | |
74 | #endif | |
75 | #endif | |
76 | ||
3d62cc61 FC |
77 | #ifndef gss_nt_service_name |
78 | #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE | |
79 | #endif | |
ba4fe07c | 80 | |
ba4fe07c AJ |
81 | static const char *LogTime(void); |
82 | ||
3ad12bda | 83 | int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, |
2e881a6f | 84 | const char *function); |
ba4fe07c AJ |
85 | |
86 | const char *squid_kerb_proxy_auth(char *proxy); | |
87 | ||
70125c34 | 88 | #define PROGRAM "negotiate_kerberos_auth_test" |
ba4fe07c | 89 | |
3ad12bda AJ |
90 | static const char * |
91 | LogTime() | |
ba4fe07c AJ |
92 | { |
93 | struct tm *tm; | |
94 | struct timeval now; | |
95 | static time_t last_t = 0; | |
96 | static char buf[128]; | |
97 | ||
98 | gettimeofday(&now, NULL); | |
99 | if (now.tv_sec != last_t) { | |
2e881a6f A |
100 | tm = localtime((const time_t *) &now.tv_sec); |
101 | strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); | |
102 | last_t = now.tv_sec; | |
ba4fe07c AJ |
103 | } |
104 | return buf; | |
105 | } | |
106 | ||
ba4fe07c | 107 | #ifndef gss_mech_spnego |
2e881a6f | 108 | static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; |
ba4fe07c AJ |
109 | gss_OID gss_mech_spnego = &_gss_mech_spnego; |
110 | #endif | |
ba4fe07c | 111 | |
3ad12bda AJ |
112 | int |
113 | check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, | |
2e881a6f | 114 | const char *function) |
26ac0430 AJ |
115 | { |
116 | if (GSS_ERROR(major_status)) { | |
2e881a6f A |
117 | OM_uint32 maj_stat, min_stat; |
118 | OM_uint32 msg_ctx = 0; | |
119 | gss_buffer_desc status_string; | |
120 | char buf[1024]; | |
121 | size_t len; | |
122 | ||
123 | len = 0; | |
124 | msg_ctx = 0; | |
08885c7f | 125 | do { |
2e881a6f A |
126 | /* convert major status code (GSS-API error) to text */ |
127 | maj_stat = gss_display_status(&min_stat, major_status, | |
128 | GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 129 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
130 | if (sizeof(buf) > len + status_string.length + 1) { |
131 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
132 | len += status_string.length; | |
133 | } | |
08885c7f MM |
134 | } else |
135 | msg_ctx = 0; | |
2e881a6f | 136 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 137 | } while (msg_ctx); |
2e881a6f A |
138 | if (sizeof(buf) > len + 2) { |
139 | snprintf(buf + len, (sizeof(buf) - len), "%s", ". "); | |
140 | len += 2; | |
141 | } | |
142 | msg_ctx = 0; | |
08885c7f | 143 | do { |
2e881a6f A |
144 | /* convert minor status code (underlying routine error) to text */ |
145 | maj_stat = gss_display_status(&min_stat, minor_status, | |
146 | GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 147 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
148 | if (sizeof(buf) > len + status_string.length) { |
149 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
150 | len += status_string.length; | |
151 | } | |
08885c7f MM |
152 | } else |
153 | msg_ctx = 0; | |
2e881a6f | 154 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 155 | } while (msg_ctx); |
2e881a6f A |
156 | fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, |
157 | buf); | |
158 | return (1); | |
ba4fe07c | 159 | } |
3ad12bda | 160 | return (0); |
ba4fe07c AJ |
161 | } |
162 | ||
3ad12bda AJ |
163 | const char * |
164 | squid_kerb_proxy_auth(char *proxy) | |
26ac0430 AJ |
165 | { |
166 | OM_uint32 major_status, minor_status; | |
3ad12bda AJ |
167 | gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; |
168 | gss_name_t server_name = GSS_C_NO_NAME; | |
169 | gss_buffer_desc service = GSS_C_EMPTY_BUFFER; | |
170 | gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | |
171 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | |
172 | char *token = NULL; | |
173 | ||
174 | setbuf(stdout, NULL); | |
175 | setbuf(stdin, NULL); | |
176 | ||
177 | if (!proxy) { | |
2e881a6f A |
178 | fprintf(stderr, "%s| %s: Error: No proxy server name\n", LogTime(), |
179 | PROGRAM); | |
180 | return NULL; | |
26ac0430 | 181 | } |
3ad12bda | 182 | service.value = xmalloc(strlen("HTTP") + strlen(proxy) + 2); |
b1218840 | 183 | snprintf((char *) service.value, strlen("HTTP") + strlen(proxy) + 2, "%s@%s", "HTTP", proxy); |
3ad12bda | 184 | service.length = strlen((char *) service.value); |
ba4fe07c | 185 | |
26ac0430 | 186 | major_status = gss_import_name(&minor_status, &service, |
2e881a6f | 187 | gss_nt_service_name, &server_name); |
ba4fe07c | 188 | |
3ad12bda | 189 | if (check_gss_err(major_status, minor_status, "gss_import_name()")) |
2e881a6f | 190 | goto cleanup; |
ba4fe07c | 191 | |
26ac0430 | 192 | major_status = gss_init_sec_context(&minor_status, |
2e881a6f A |
193 | GSS_C_NO_CREDENTIAL, &gss_context, server_name, |
194 | gss_mech_spnego, | |
195 | 0, | |
196 | 0, | |
197 | GSS_C_NO_CHANNEL_BINDINGS, | |
198 | &input_token, NULL, &output_token, NULL, NULL); | |
3ad12bda AJ |
199 | |
200 | if (check_gss_err(major_status, minor_status, "gss_init_sec_context()")) | |
2e881a6f | 201 | goto cleanup; |
ba4fe07c | 202 | |
26ac0430 | 203 | if (output_token.length) { |
4ebcf1ce MM |
204 | token = (char *) xmalloc((size_t)base64_encode_len((int)output_token.length)); |
205 | base64_encode_str(token, base64_encode_len((int)output_token.length), | |
206 | (const char *) output_token.value, (int)output_token.length); | |
26ac0430 | 207 | } |
2e881a6f | 208 | cleanup: |
26ac0430 AJ |
209 | gss_delete_sec_context(&minor_status, &gss_context, NULL); |
210 | gss_release_buffer(&minor_status, &service); | |
211 | gss_release_buffer(&minor_status, &input_token); | |
212 | gss_release_buffer(&minor_status, &output_token); | |
213 | gss_release_name(&minor_status, &server_name); | |
ba4fe07c | 214 | |
26ac0430 | 215 | return token; |
ba4fe07c AJ |
216 | } |
217 | ||
3ad12bda AJ |
218 | int |
219 | main(int argc, char *argv[]) | |
26ac0430 | 220 | { |
26ac0430 | 221 | const char *Token; |
3ad12bda | 222 | int count; |
ba4fe07c | 223 | |
3ad12bda | 224 | if (argc < 2) { |
2e881a6f A |
225 | fprintf(stderr, "%s| %s: Error: No proxy server name given\n", |
226 | LogTime(), PROGRAM); | |
bc30ad64 | 227 | return 99; |
3ad12bda AJ |
228 | } |
229 | if (argc == 3) { | |
2e881a6f A |
230 | count = atoi(argv[2]); |
231 | while (count > 0) { | |
232 | Token = (const char *) squid_kerb_proxy_auth(argv[1]); | |
233 | fprintf(stdout, "YR %s\n", Token ? Token : "NULL"); | |
755494da | 234 | --count; |
2e881a6f A |
235 | } |
236 | fprintf(stdout, "QQ\n"); | |
3ad12bda | 237 | } else { |
2e881a6f A |
238 | Token = (const char *) squid_kerb_proxy_auth(argv[1]); |
239 | fprintf(stdout, "Token: %s\n", Token ? Token : "NULL"); | |
26ac0430 | 240 | } |
ba4fe07c | 241 | |
bc30ad64 | 242 | return 0; |
ba4fe07c | 243 | } |
b1218840 | 244 | |
6989c6dc | 245 | #else |
074d6a40 | 246 | #include <cstdlib> |
6989c6dc AJ |
247 | int |
248 | main(int argc, char *argv[]) | |
249 | { | |
bc30ad64 | 250 | return -1; |
6989c6dc | 251 | } |
b1218840 | 252 | |
3ad12bda | 253 | #endif /* HAVE_GSSAPI */ |
f53969cc | 254 |