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