]>
Commit | Line | Data |
---|---|---|
ca02e0ec | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 The Squid Software Foundation and contributors |
ca02e0ec AJ |
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 |
75f3c557 MM |
36 | #if USE_APPLE_KRB5 |
37 | #define GSSKRB_APPLE_DEPRECATED(x) | |
38 | #endif | |
70125c34 | 39 | |
074d6a40 AJ |
40 | #include <cerrno> |
41 | #include <cstring> | |
42 | #include <ctime> | |
70125c34 | 43 | #if HAVE_NETDB_H |
ba4fe07c | 44 | #include <netdb.h> |
70125c34 AJ |
45 | #endif |
46 | #if HAVE_UNISTD_H | |
ba4fe07c | 47 | #include <unistd.h> |
70125c34 | 48 | #endif |
ba4fe07c | 49 | |
70125c34 | 50 | #include "base64.h" |
3ad12bda AJ |
51 | #include "util.h" |
52 | ||
1a22a39e MM |
53 | #if USE_HEIMDAL_KRB5 |
54 | #if HAVE_GSSAPI_GSSAPI_H | |
55 | #include <gssapi/gssapi.h> | |
56 | #elif HAVE_GSSAPI_H | |
57 | #include <gssapi.h> | |
58 | #endif | |
59 | #elif USE_GNUGSS | |
60 | #if HAVE_GSS_H | |
61 | #include <gss.h> | |
62 | #endif | |
63 | #else | |
3ad12bda AJ |
64 | #if HAVE_GSSAPI_GSSAPI_H |
65 | #include <gssapi/gssapi.h> | |
66 | #elif HAVE_GSSAPI_H | |
67 | #include <gssapi.h> | |
75a8c92e | 68 | #endif |
3ad12bda AJ |
69 | #if HAVE_GSSAPI_GSSAPI_KRB5_H |
70 | #include <gssapi/gssapi_krb5.h> | |
75a8c92e | 71 | #endif |
3ad12bda AJ |
72 | #if HAVE_GSSAPI_GSSAPI_GENERIC_H |
73 | #include <gssapi/gssapi_generic.h> | |
75a8c92e AJ |
74 | #endif |
75 | #if HAVE_GSSAPI_GSSAPI_EXT_H | |
76 | #include <gssapi/gssapi_ext.h> | |
77 | #endif | |
78 | #endif | |
79 | ||
3d62cc61 FC |
80 | #ifndef gss_nt_service_name |
81 | #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE | |
82 | #endif | |
ba4fe07c | 83 | |
ba4fe07c AJ |
84 | static const char *LogTime(void); |
85 | ||
3ad12bda | 86 | int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, |
2e881a6f | 87 | const char *function); |
ba4fe07c AJ |
88 | |
89 | const char *squid_kerb_proxy_auth(char *proxy); | |
90 | ||
70125c34 | 91 | #define PROGRAM "negotiate_kerberos_auth_test" |
ba4fe07c | 92 | |
3ad12bda AJ |
93 | static const char * |
94 | LogTime() | |
ba4fe07c AJ |
95 | { |
96 | struct tm *tm; | |
97 | struct timeval now; | |
98 | static time_t last_t = 0; | |
99 | static char buf[128]; | |
100 | ||
101 | gettimeofday(&now, NULL); | |
102 | if (now.tv_sec != last_t) { | |
2e881a6f A |
103 | tm = localtime((const time_t *) &now.tv_sec); |
104 | strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm); | |
105 | last_t = now.tv_sec; | |
ba4fe07c AJ |
106 | } |
107 | return buf; | |
108 | } | |
109 | ||
ba4fe07c | 110 | #ifndef gss_mech_spnego |
2e881a6f | 111 | static gss_OID_desc _gss_mech_spnego = {6, (void *) "\x2b\x06\x01\x05\x05\x02"}; |
ba4fe07c AJ |
112 | gss_OID gss_mech_spnego = &_gss_mech_spnego; |
113 | #endif | |
ba4fe07c | 114 | |
3ad12bda AJ |
115 | int |
116 | check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, | |
2e881a6f | 117 | const char *function) |
26ac0430 AJ |
118 | { |
119 | if (GSS_ERROR(major_status)) { | |
2e881a6f A |
120 | OM_uint32 maj_stat, min_stat; |
121 | OM_uint32 msg_ctx = 0; | |
122 | gss_buffer_desc status_string; | |
123 | char buf[1024]; | |
124 | size_t len; | |
125 | ||
126 | len = 0; | |
127 | msg_ctx = 0; | |
08885c7f | 128 | do { |
2e881a6f A |
129 | /* convert major status code (GSS-API error) to text */ |
130 | maj_stat = gss_display_status(&min_stat, major_status, | |
131 | GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 132 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
133 | if (sizeof(buf) > len + status_string.length + 1) { |
134 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
135 | len += status_string.length; | |
136 | } | |
08885c7f MM |
137 | } else |
138 | msg_ctx = 0; | |
2e881a6f | 139 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 140 | } while (msg_ctx); |
2e881a6f A |
141 | if (sizeof(buf) > len + 2) { |
142 | snprintf(buf + len, (sizeof(buf) - len), "%s", ". "); | |
143 | len += 2; | |
144 | } | |
145 | msg_ctx = 0; | |
08885c7f | 146 | do { |
2e881a6f A |
147 | /* convert minor status code (underlying routine error) to text */ |
148 | maj_stat = gss_display_status(&min_stat, minor_status, | |
149 | GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 150 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
151 | if (sizeof(buf) > len + status_string.length) { |
152 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
153 | len += status_string.length; | |
154 | } | |
08885c7f MM |
155 | } else |
156 | msg_ctx = 0; | |
2e881a6f | 157 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 158 | } while (msg_ctx); |
2e881a6f A |
159 | fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, |
160 | buf); | |
161 | return (1); | |
ba4fe07c | 162 | } |
3ad12bda | 163 | return (0); |
ba4fe07c AJ |
164 | } |
165 | ||
3ad12bda AJ |
166 | const char * |
167 | squid_kerb_proxy_auth(char *proxy) | |
26ac0430 AJ |
168 | { |
169 | OM_uint32 major_status, minor_status; | |
3ad12bda AJ |
170 | gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; |
171 | gss_name_t server_name = GSS_C_NO_NAME; | |
172 | gss_buffer_desc service = GSS_C_EMPTY_BUFFER; | |
173 | gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | |
174 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | |
175 | char *token = NULL; | |
176 | ||
177 | setbuf(stdout, NULL); | |
178 | setbuf(stdin, NULL); | |
179 | ||
180 | if (!proxy) { | |
2e881a6f A |
181 | fprintf(stderr, "%s| %s: Error: No proxy server name\n", LogTime(), |
182 | PROGRAM); | |
183 | return NULL; | |
26ac0430 | 184 | } |
3ad12bda | 185 | service.value = xmalloc(strlen("HTTP") + strlen(proxy) + 2); |
b1218840 | 186 | snprintf((char *) service.value, strlen("HTTP") + strlen(proxy) + 2, "%s@%s", "HTTP", proxy); |
3ad12bda | 187 | service.length = strlen((char *) service.value); |
ba4fe07c | 188 | |
26ac0430 | 189 | major_status = gss_import_name(&minor_status, &service, |
2e881a6f | 190 | gss_nt_service_name, &server_name); |
ba4fe07c | 191 | |
aadbbd7d AJ |
192 | if (!check_gss_err(major_status, minor_status, "gss_import_name()")) { |
193 | ||
194 | major_status = gss_init_sec_context(&minor_status, | |
195 | GSS_C_NO_CREDENTIAL, &gss_context, server_name, | |
196 | gss_mech_spnego, | |
197 | 0, | |
198 | 0, | |
199 | GSS_C_NO_CHANNEL_BINDINGS, | |
200 | &input_token, NULL, &output_token, NULL, NULL); | |
201 | ||
202 | if (!check_gss_err(major_status, minor_status, "gss_init_sec_context()") && output_token.length) { | |
203 | token = (char *) xcalloc(base64_encode_len(output_token.length), 1); | |
204 | struct base64_encode_ctx ctx; | |
205 | base64_encode_init(&ctx); | |
206 | size_t blen = base64_encode_update(&ctx, reinterpret_cast<uint8_t*>(token), output_token.length, reinterpret_cast<const uint8_t*>(output_token.value)); | |
207 | blen += base64_encode_final(&ctx, reinterpret_cast<uint8_t*>(token)+blen); | |
208 | } | |
26ac0430 | 209 | } |
aadbbd7d | 210 | |
26ac0430 AJ |
211 | gss_delete_sec_context(&minor_status, &gss_context, NULL); |
212 | gss_release_buffer(&minor_status, &service); | |
213 | gss_release_buffer(&minor_status, &input_token); | |
214 | gss_release_buffer(&minor_status, &output_token); | |
215 | gss_release_name(&minor_status, &server_name); | |
ba4fe07c | 216 | |
26ac0430 | 217 | return token; |
ba4fe07c AJ |
218 | } |
219 | ||
3ad12bda AJ |
220 | int |
221 | main(int argc, char *argv[]) | |
26ac0430 | 222 | { |
26ac0430 | 223 | const char *Token; |
3ad12bda | 224 | int count; |
ba4fe07c | 225 | |
3ad12bda | 226 | if (argc < 2) { |
2e881a6f A |
227 | fprintf(stderr, "%s| %s: Error: No proxy server name given\n", |
228 | LogTime(), PROGRAM); | |
bc30ad64 | 229 | return 99; |
3ad12bda AJ |
230 | } |
231 | if (argc == 3) { | |
2e881a6f A |
232 | count = atoi(argv[2]); |
233 | while (count > 0) { | |
234 | Token = (const char *) squid_kerb_proxy_auth(argv[1]); | |
235 | fprintf(stdout, "YR %s\n", Token ? Token : "NULL"); | |
755494da | 236 | --count; |
2e881a6f A |
237 | } |
238 | fprintf(stdout, "QQ\n"); | |
3ad12bda | 239 | } else { |
2e881a6f A |
240 | Token = (const char *) squid_kerb_proxy_auth(argv[1]); |
241 | fprintf(stdout, "Token: %s\n", Token ? Token : "NULL"); | |
26ac0430 | 242 | } |
ba4fe07c | 243 | |
bc30ad64 | 244 | return 0; |
ba4fe07c | 245 | } |
b1218840 | 246 | |
6989c6dc | 247 | #else |
074d6a40 | 248 | #include <cstdlib> |
6989c6dc AJ |
249 | int |
250 | main(int argc, char *argv[]) | |
251 | { | |
bc30ad64 | 252 | return -1; |
6989c6dc | 253 | } |
b1218840 | 254 | |
3ad12bda | 255 | #endif /* HAVE_GSSAPI */ |
f53969cc | 256 |